/* ==========================================================
 * sco.modal.js
 * http://github.com/terebentina/sco.js
 * ==========================================================
 * Copyright 2013 Dan Caragea.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ========================================================== */

/*jshint laxcomma:true, sub:true, browser:true, jquery:true, devel:true, eqeqeq:false */
/*global Spinner:true */

;
(function($, undefined) {
    "use strict";

    var pluginName = 'yyt_modal';

    var modalStack = []; //模态框堆栈

    function Modal(options) {
        this.options = $.extend({}, $.fn[pluginName].defaults, options);
        this.$modal = $(this.options.target).addClass('yyt-modal fade').hide();
    }

    function getMaxHeight(hasTitle, hasFooter, isFull) {
        var totalHeight = $(window).height();
        if (!isFull) {
            totalHeight -= totalHeight * 0.1;
        }
        if (hasTitle) {
            totalHeight -= 40;
        }
        if (hasFooter) {
            totalHeight -= 53;
        }
        return totalHeight + 'px';
    }

    $.extend(Modal.prototype, {
        render: function() {
                var self = this,
                    $backdrop;

                if (!this.options.nobackdrop) {
                    $backdrop = $('.yyt-modal-backdrop');
                }
                if (!this.$modal.length) {
                    this.$modal = $('<div class="yyt-modal-wrap"><div class="yyt-modal ' + (self.options.footer ? 'has-footer' : '') + ' ' + (self.options.title ? 'has-header' : '') + ' fade ' + (this.options.cssclass || this.options.className || "") + '" id="' + this.options.target.substr(1) + '">' +
                        (function() {
                            if (self.options.title) {
                                return '<div class="yyt-modal-header">' +
                                    (self.options.enableClose ? '<a class="close" title="关闭" href="javascript:;" data-dismiss="modal"><i></i></a>' : '') +
                                    (self.options.maxmin ? "<a class='maximizable' href='javascript:;'><i class='yyt-icon maximize' title='最大化'></i></a>" : "") + '<h4>&nbsp;</h4></div>';
                            }
                            return ''
                        })() +
                        (function() {
                            //没有title,想要close
                            var html = '';
                            if ((self.options.enableClose || self.options.isShowClose) && !self.options.title) {
                                html += '<a class="close no-title" title="关闭" href="#" data-dismiss="modal"><i></i>' +
                                    '  </a>'
                            }
                            return html;
                        })() +
                        '<div class="inner" style="overflow: auto"/>' +
                        (function() {
                            var footer = '';
                            if (self.options.footer) {
                                footer = self.options.footer;
                            }
                            return footer
                        })() + '</div></div>'
                    ).appendTo(this.options.appendTo).hide();

                    if (this.options.zIndex) {
                        this.$modal.css('z-index', Number(this.options.zIndex));
                    }

                    this.$main = this.$modal.find('.yyt-modal');
                    this.$inner = this.$modal.find('.inner').first();
                }

                this.$modal.find('.yyt-modal-header h4').html(this.options.title);

                // if (this.options.area) {
                //     this.$modal.find('.yyt-modal').addClass('custom-area');
                //     var area = this.options.area;
                //     this.options.width = parseInt(area[1]) > 200 ? area[0] : '200px';
                //     this.options.height = parseInt(area[0]) > 150 ? area[0] : '150px';
                // }
                if (this.options.width) {
                    this.$modal.find('.yyt-modal').width(this.options.width);
                }

                if (this.options.left !== undefined) {
                    this.$modal.css({
                        'left': this.options.left
                    });
                }

                if (this.options.height) {
                    this.$modal.find('.yyt-modal').addClass('custom-area');
                    this.$modal.find('.yyt-modal').height(this.options.height);
                    this.$modal.find('.yyt-modal').css({
                        maxHeight: this.options.maxHeight
                    })
                } else {
                    this.$modal.find('.inner').css({
                        maxHeight: getMaxHeight(this.options.title, this.options.footer)
                    })
                }

                if (this.options.top !== undefined) {
                    this.$modal.css({
                        'top': this.options.top
                    });
                }

                if (this.options.keyboard) {
                    this.escape();
                }

                if (!this.options.nobackdrop) {
                    if (!$backdrop.length) {
                        $backdrop = $('<div class="yyt-modal-backdrop fade" />').appendTo(this.options.appendTo);
                        if (this.options.zIndex) {
                            $backdrop.css('z-index', Number(this.options.zIndex) - 1);
                        }
                    }
                    $backdrop[0].offsetWidth; // force reflow
                    $backdrop.addClass('in');
                    $backdrop.show();

                }

                this.$modal.off('close.' + pluginName).on('close.' + pluginName, function() {
                    self.close.call(self);
                });
                if (this.options.remote !== undefined && this.options.remote != '' && this.options.remote !== '#') {
                    var spinner;
                    if (typeof Spinner == 'function') {
                        spinner = new Spinner({
                            color: '#3d9bce'
                        }).spin(this.$modal[0]);
                    }
                    this.$modal.find('.inner').load(this.options.remote, function() {
                        if (spinner) {
                            spinner.stop();
                        }
                        if (self.options.cache) {
                            self.options.content = $(this).html();
                            delete self.options.remote;
                        }
                    });
                } else if (this.options.type === 'iframe') {
                    // weizf+ 20210425 当类型为模态框类型时 content为iframe的url
                    var content = this.options.content;
                    var ts = new Date().getTime();
                    content = "<iframe disabled-redirect='true' name=" + ts + " src='" + content + "' style='width:100%;height:100%;' vspace='0' hspace='0' frameborder='0'></iframe>";
                    this.$modal.find('.inner').html(content);
                    // 当类型为模态框类型时 iframe加载完成后触发load事件
                    var modalIframe = $('iframe[name=' + ts + ']');
                    modalIframe.on('load', function(e) {
                        self.options.onload && self.options.onload(e, this);
                    })
                } else {
                    this.$modal.find('.inner').html(this.options.content);
                }

                this.$modal.show().find('.yyt-modal').addClass('in');

                $(this.options.target).on('click', '.yyt-icon.maximize', function(e) {
                    e.stopPropagation();
                    self.maxWindow();
                    self.isMaxStatus = true;
                }).on('click', '.yyt-icon.restore', function(e) {
                    e.stopPropagation();
                    self.restoreWindow();
                    self.isMaxStatus = false;
                });

                if (self.options.isDefaultMax) {
                    this.maxWindow();
                    this.isMaxStatus = true;
                }
                $(window).on('resize', function() {
                    if (self.isMaxStatus)
                        self.maxWindow();
                });
                return this;
            }

            ,
        close: function() {
                function doClose() {
                    this.$modal.remove();
                    $(document).off('keyup.' + pluginName);

                    if (!$(document).find('.yyt-modal.fade').is(':visible')) {
                        $('.yyt-modal-backdrop').remove();
                    }
                    this.$modal = null;
                    modalStack.shift();
                    return this;
                }
                var _this = this;
                if (typeof this.options.beforeClose == 'function') {
                    var fun = this.options.beforeClose.call(this);
                    //是否promise对象
                    if (fun && typeof fun.then == 'function') {
                        fun.then(function() {
                            doClose.call(_this);
                        })
                    } else if (fun !== false) {
                        doClose.call(_this);
                    }
                } else {
                    doClose.call(_this);
                }
            }


            ,
        destroy: function() {
                function doDestory() {
                    if (!this.options.closeIsDestory) {
                        this.$modal.hide();
                        $('.yyt-modal-backdrop').hide();
                        return this;
                    }
                    if (this.$modal && typeof this.$modal.remove == 'function') {
                        this.$modal.remove();
                    }
                    $(document).off('keyup.' + pluginName);

                    if (!$(document).find('.yyt-modal.fade').is(':visible')) {
                        $('.yyt-modal-backdrop').remove();
                    }
                    this.$modal = null;
                    modalStack.shift();
                    return this;
                }
                // modify by caiwc 2020-04-24 防止多次调destroy.导致modal取不到
                if (!this.$modal) return;
                var _this = this;
                if (typeof this.options.beforeClose == 'function') {
                    var fun = this.options.beforeClose.call(this);
                    if (fun && typeof fun.then == 'function') {
                        fun.then(function() {
                            doDestory.call(_this);
                        })
                    } else if (fun !== false) {
                        doDestory.call(_this);
                    }
                } else {
                    doDestory.call(_this);
                }
            }

            ,
        escape: function() {
                var self = this;
                $(document).off("keyup").on('keyup', function(e) {
                    if (e.which == 27 && self.options.enableClose) {
                        var modal = modalStack[0];
                        modal.destroy();
                    }
                });
            }

            ,
        maxWindow: function() {
                this.$modal.find('.yyt-modal').addClass('yyt-modal-fullscreen');
                this.$modal.find('.maximize').removeClass('maximize').addClass('restore').attr('title', '向下还原');
            }

            ,
        restoreWindow: function() {
            this.$modal.find('.yyt-modal').removeClass('yyt-modal-fullscreen');
            this.$modal.find('.restore').removeClass('restore').addClass('maximize').attr('title', '最大化');
        },
        getContent: function() {
                var content = this.$modal.find('.inner').children();
                return $(content);
            }
            //add by  xiezf 以前的show方法改为render show：只做css显示
            ,
        show: function() {
            this.$modal.show();
            if (!this.options.nobackdrop) {
                var $backdrop = $('.yyt-modal-backdrop');
                if (!$backdrop.length) {
                    $backdrop = $('<div class="yyt-modal-backdrop fade" />').appendTo(this.options.appendTo);
                    if (this.options.zIndex) {
                        $backdrop.css('z-index', Number(this.options.zIndex) - 1);
                    }
                }
                $backdrop[0].offsetWidth; // force reflow
                $backdrop.addClass('in');
                $backdrop.show();
            }
        }
    });


    $.fn[pluginName] = function(options) {
        return this.each(function() {
            var obj;
            if (!(obj = $.data(this, pluginName))) {
                var $this = $(this),
                    data = $this.data(),
                    opts = $.extend({}, options, data);
                if ($this.attr('href') !== '' && $this.attr('href') != '#') {
                    opts.remote = $this.attr('href');
                }
                obj = new Modal(opts);
                $.data(this, pluginName, obj);
            }
            obj.render();
        });
    };


    $[pluginName] = function(options) {
        var modal = new Modal(options);
        modalStack.unshift(modal); //模态框实例插入模态堆栈 最新的置于最前
        return modal;
    };


    $.fn[pluginName].defaults = {
        title: '' // modal title
            ,
        target: '#modal' // the modal id. MUST be an id for now.
            ,
        content: '' // the static modal content (in case it's not loaded via ajax)
            ,
        appendTo: 'body' // where should the modal be appended to (default to document.body). Added for unit tests, not really needed in real life.
            ,
        cache: false // should we cache the output of the ajax calls so that next time they're shown from cache?
            ,
        keyboard: true,
        nobackdrop: false,
        maxmin: false,
        isDefaultMax: false,
        area: null,
        maxHeight: '90%',
        beforeClose: null
    };


    $(document).on('click.' + pluginName, '[data-trigger="modal"]', function() {
        $(this)[pluginName]();
        if ($(this).is('a')) {
            return false;
        }
    }).on('click.' + pluginName, '[data-dismiss="modal"]', function(e) {
        e.preventDefault();
        $(this).closest('.modal').trigger('close');
    })

})(jQuery);

/* ==========================================================
 * sco.tooltip.js
 * http://github.com/terebentina/sco.js
 * ==========================================================
 * Copyright 2013 Dan Caragea.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ========================================================== */

/*jshint laxcomma:true, sub:true, browser:true, jquery:true, smarttabs:true, eqeqeq:false */

;
(function($, undefined) {
    "use strict";

    var pluginName = 'yyt_tooltip';

    function Tooltip($trigger, options) {
        this.options = $.extend({}, $.fn[pluginName].defaults, options);
        this.$trigger = this.$target = $trigger;
        this.leaveTimeout = null;
        if (options.appendto && options.appendto != 'body') {
            this.options.appendTo = $(options.appendto);
        }
        if (this.options.appendTo && this.options.appendTo != 'body') {
            this.options.appendTo = $(this.options.appendTo);
        }
        this.$tooltip = $('<div class="tooltip yyt-tooltip"><span></span><div class="yyt-pointer"></div></div>').appendTo(this.options.appendTo).hide();
        if (this.options.contentElem !== undefined && this.options.contentElem !== null) {
            this.options.yytcontent = $(this.options.contentElem).html();
        } else if (this.options.contentAttr !== undefined && this.options.contentAttr !== null) {
            this.options.yytcontent = this.$trigger.attr(this.options.contentAttr);
        }
        if (this.$trigger && this.$trigger.attr('title')) {
            this.$trigger.data('originalTitle', this.$trigger.attr('title'));
        }
        this.$tooltip.find('span').html(this.options.yytcontent);
        if (this.options.cssclass != '') {
            this.$tooltip.addClass(this.options.cssclass);
        }
        if (this.options.target !== undefined) {
            this.$target = $(this.options.target);
        }
        if (!this.$tooltip.context) {
            this.$tooltip.context = $(this.$tooltip[0])
        }
        if (this.options.hoverable) {
            var self = this;
            this.$tooltip.on('mouseenter.' + pluginName, $.proxy(this.show, self))
                .on('mouseleave.' + pluginName, $.proxy(this.do_mouseleave, self))
                .on('close.' + pluginName, $.proxy(this.hide, self));
        }
    }


    $.extend(Tooltip.prototype, {
        show: function(allowMirror) {
                if (allowMirror === undefined) {
                    allowMirror = true;
                }
                this.$tooltip.removeClass('pos_w pos_e pos_n pos_s pos_nw pos_ne pos_se pos_sw pos_center').addClass('pos_' + this.options.position);

                var targetBox = this.$target.offset(),
                    tooltipBox = {
                        left: 0,
                        top: 0,
                        width: Math.floor(this.$tooltip.outerWidth()),
                        height: Math.floor(this.$tooltip.outerHeight())
                    },
                    pointerBox = {
                        left: 0,
                        top: 0,
                        width: Math.floor(this.$tooltip.find('.yyt-pointer').outerWidth()),
                        height: Math.floor(this.$tooltip.find('.yyt-pointer').outerHeight())
                    },
                    docBox = {
                        left: $(document).scrollLeft(),
                        top: $(document).scrollTop(),
                        width: $(window).width(),
                        height: $(window).height()
                    };
                targetBox.left = Math.floor(targetBox.left);
                targetBox.top = Math.floor(targetBox.top);
                targetBox.width = Math.floor(this.$target.outerWidth());
                targetBox.height = Math.floor(this.$target.outerHeight());
                if (targetBox.left == 0 && targetBox.top == 0 && targetBox.width == 0 && targetBox.height == 0) {
                    return
                }
                if (this.options.position === 'w') {
                    tooltipBox.left = targetBox.left - tooltipBox.width - pointerBox.width;
                    tooltipBox.top = targetBox.top + Math.floor((targetBox.height - tooltipBox.height) / 2);
                    pointerBox.left = tooltipBox.width;
                    pointerBox.top = Math.floor(targetBox.height / 2);
                } else if (this.options.position === 'e') {
                    tooltipBox.left = targetBox.left + targetBox.width + pointerBox.width;
                    tooltipBox.top = targetBox.top + Math.floor((targetBox.height - tooltipBox.height) / 2);
                    pointerBox.left = -pointerBox.width;
                    pointerBox.top = Math.floor(tooltipBox.height / 2);
                } else if (this.options.position === 'n') {
                    tooltipBox.left = targetBox.left - Math.floor((tooltipBox.width - targetBox.width) / 2);
                    tooltipBox.top = targetBox.top - tooltipBox.height - pointerBox.height;
                    pointerBox.left = Math.floor(tooltipBox.width / 2);
                    pointerBox.top = tooltipBox.height;
                } else if (this.options.position === 's') {
                    tooltipBox.left = targetBox.left - Math.floor((tooltipBox.width - targetBox.width) / 2);
                    tooltipBox.top = targetBox.top + targetBox.height + pointerBox.height;
                    pointerBox.left = Math.floor(tooltipBox.width / 2);
                    pointerBox.top = -pointerBox.height;
                } else if (this.options.position === 'nw') {
                    tooltipBox.left = targetBox.left - tooltipBox.width + pointerBox.width; // +pointerBox.width because yyt-pointer is under
                    tooltipBox.top = targetBox.top - tooltipBox.height - pointerBox.height;
                    pointerBox.left = tooltipBox.width - pointerBox.width;
                    pointerBox.top = tooltipBox.height;
                } else if (this.options.position === 'ne') {
                    tooltipBox.left = targetBox.left + targetBox.width - pointerBox.width;
                    tooltipBox.top = targetBox.top - tooltipBox.height - pointerBox.height;
                    pointerBox.left = 1;
                    pointerBox.top = tooltipBox.height;
                } else if (this.options.position === 'se') {
                    tooltipBox.left = targetBox.left + targetBox.width - pointerBox.width;
                    tooltipBox.top = targetBox.top + targetBox.height + pointerBox.height;
                    pointerBox.left = 1;
                    pointerBox.top = -pointerBox.height;
                } else if (this.options.position === 'sw') {
                    tooltipBox.left = targetBox.left - tooltipBox.width + pointerBox.width;
                    tooltipBox.top = targetBox.top + targetBox.height + pointerBox.height;
                    pointerBox.left = tooltipBox.width - pointerBox.width;
                    pointerBox.top = -pointerBox.height;
                } else if (this.options.position === 'center') {
                    tooltipBox.left = targetBox.left + Math.floor((targetBox.width - tooltipBox.width) / 2);
                    tooltipBox.top = targetBox.top + Math.floor((targetBox.height - tooltipBox.height) / 2);
                    allowMirror = false;
                    this.$tooltip.find('.yyt-pointer').hide();
                }

                // if the tooltip is out of bounds we first mirror its position
                if (allowMirror) {
                    var newpos = this.options.position,
                        do_mirror = false;
                    if (tooltipBox.left < docBox.left) {
                        newpos = newpos.replace('w', 'e');
                        do_mirror = true;
                    } else if (tooltipBox.left + tooltipBox.width > docBox.left + docBox.width) {
                        newpos = newpos.replace('e', 'w');
                        do_mirror = true;
                    }
                    if (tooltipBox.top < docBox.top) {
                        newpos = newpos.replace('n', 's');
                        do_mirror = true;
                    } else if (tooltipBox.top + tooltipBox.height > docBox.top + docBox.height) {
                        newpos = newpos.replace('s', 'n');
                        do_mirror = true;
                    }
                    if (do_mirror) {
                        this.options.position = newpos;
                        this.show(false);
                        return this;
                    }
                }

                // if we're here, it's definitely after the mirroring or the position is center
                // this part is for slightly moving the tooltip if it's still out of bounds
                var pointer_left = null,
                    pointer_top = null;
                if (tooltipBox.left < docBox.left) {
                    pointer_left = tooltipBox.left - docBox.left - pointerBox.width / 2;
                    tooltipBox.left = docBox.left;
                } else if (tooltipBox.left + tooltipBox.width > docBox.left + docBox.width) {
                    pointer_left = tooltipBox.left - docBox.left - docBox.width + tooltipBox.width - pointerBox.width / 2;
                    tooltipBox.left = docBox.left + docBox.width - tooltipBox.width;
                }
                if (tooltipBox.top < docBox.top) {
                    pointer_top = tooltipBox.top - docBox.top - pointerBox.height / 2;
                    tooltipBox.top = docBox.top;
                } else if (tooltipBox.top + tooltipBox.height > docBox.top + docBox.height) {
                    pointer_top = tooltipBox.top - docBox.top - docBox.height + tooltipBox.height - pointerBox.height / 2;
                    tooltipBox.top = docBox.top + docBox.height - tooltipBox.height;
                }

                this.$tooltip.css({
                    left: tooltipBox.left,
                    top: tooltipBox.top
                });
                if (pointer_left !== null) {
                    // this.$tooltip.find('.yyt-pointer').css('margin-left', pointer_left);
                }
                if (pointer_top !== null) {
                    this.$tooltip.find('.yyt-pointer').css('margin-top', '+=' + pointer_top);
                }

                this.$trigger.removeAttr('title');
                var content = this.$target.clone().data('yytcontent') || this.options.yytcontent;
                this.$tooltip.find('span').html(content);
                if (typeof content != 'undefined' && content) {
                    this.$tooltip.show();
                }
                return this;
            }

            ,
        hide: function() {
                if (this.$trigger.data('originalTitle')) {
                    this.$trigger.attr('title', this.$trigger.data('originalTitle'));
                }
                if (typeof this.options.on_close == 'function') {
                    this.options.on_close.call(this);
                }
                this.$tooltip.hide();
            }

            ,
        do_mouseenter: function(opts) {
                if (this.options.type != 'click') {
                    if (this.leaveTimeout !== null) {
                        clearTimeout(this.leaveTimeout);
                        this.leaveTimeout = null;
                    }
                    var self = this;
                    this.leaveTimeout = setTimeout(function() {
                        clearTimeout(self.leaveTimeout);
                        self.leaveTimeout = null;
                        self.show();
                    }, this.options.delay);
                }

            }

            ,
        do_mouseleave: function() {
            var self = this;
            if (this.options.type == 'click') return;

            if (this.leaveTimeout !== null) {
                clearTimeout(this.leaveTimeout);
                this.leaveTimeout = null;
            }
            self.hide();
        }
    });

    $.fn[pluginName] = function(options) {
        var method = null,
            first_run = false;
        if (typeof options == 'string') {
            method = options;
        }
        return this.each(function() {
            var obj;
            if (!(obj = $.data(this, pluginName))) {
                var $this = $(this),
                    data = $this.data(),
                    opts;
                first_run = true;
                if (typeof options === 'object') {
                    opts = $.extend({}, options, data);
                } else {
                    opts = data;
                }
                obj = new Tooltip($this, opts);
                $.data(this, pluginName, obj);
            }
            $.extend(obj.options, options);
            if (method) {
                obj[method]();
            } else if (first_run) {
                $(this).on('mouseenter.' + pluginName, function() {
                    obj.do_mouseenter();
                }).on('mouseleave.' + pluginName, function() {
                    obj.do_mouseleave();
                });
            } else {
                obj.show();
            }

        });
    };


    $[pluginName] = function(elem, options) {
        if (typeof elem === 'string') {
            elem = $(elem);
        }

        return new Tooltip(elem, options);
    };


    $.fn[pluginName].defaults = {
        contentElem: null,
        contentAttr: null,
        yytcontent: '',
        hoverable: true // should mouse over tooltip hold the tooltip or not?
            ,
        delay: 500,
        cssclass: '',
        position: 'n' // n,s,e,w,ne,nw,se,sw,center
            ,
        autoclose: true,
        appendTo: 'body' // where should the tooltips be appended to (default to document.body). Added for unit tests, not really needed in real life.
    };

    $(document).off('mouseenter.' + pluginName).on('mouseenter.' + pluginName, '[data-yyttrigger="tooltip"]', function(e) {
        if ($(this).data('type') != 'click')
            $(this)[pluginName]('do_mouseenter');
    }).off('mouseleave.' + pluginName).on('mouseleave.' + pluginName, '[data-yyttrigger="tooltip"]', function(e) {
        if ($(this).data('type') != 'click')
            $(this)[pluginName]('do_mouseleave');
    });

    $(document).off('click.' + pluginName, '[data-dismiss="tooltip"]').on('click.' + pluginName, '[data-dismiss="tooltip"]', function(e) {
        $(this).closest('.tooltip').trigger('close');
    });

    //支持点击的
    $(document).on('click', function() {
        $('.tooltip').hide();
    }).on('click.' + pluginName, '[data-yyttrigger="tooltip"]', function(e) {
        e.stopPropagation();
        $('.tooltip').hide();
        $(this)[pluginName]('show');
    });
})(jQuery);
(function(root, factory) {

    'use strict';

    if (typeof define === 'function' && define.amd) {
        define(factory);
    } else if (typeof exports !== 'undefined') {
        module.exports = factory();
    } else {
        root.yytEleResize = factory();
    }

}(this, function() {

    /**
     * 监听节点resize, 浏览器兼容IE9+
     *
     * example:
     *  EleResize.on(resizeDiv, function);
     *  EleResize.off(resizeDiv, listener)
     */
    var EleResize = {
        _handleResize: function(e) {
            var ele = e.target || e.srcElement;
            var trigger = ele.__resizeTrigger__;
            if (trigger) {
                var handlers = trigger.__z_resizeListeners;
                if (handlers) {
                    var size = handlers.length;
                    for (var i = 0; i < size; i++) {
                        var h = handlers[i];
                        var handler = h.handler;
                        var context = h.context;
                        handler.apply(context, [e]);
                    }
                }
            }
        },
        _removeHandler: function(ele, handler, context) {
            var handlers = ele.__z_resizeListeners;
            if (handlers) {
                var size = handlers.length;
                for (var i = 0; i < size; i++) {
                    var h = handlers[i];
                    if (h.handler === handler && h.context === context) {
                        handlers.splice(i, 1);
                        return;
                    }
                }
            }
        },
        _createResizeTrigger: function(ele) {
            var obj = document.createElement('object');
            obj.setAttribute('style',
                'display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden;opacity: 0; pointer-events: none; z-index: -1;');
            obj.onload = EleResize._handleObjectLoad;
            obj.type = 'text/html';
            ele.appendChild(obj);
            obj.data = 'about:blank';
            return obj;
        },
        _handleObjectLoad: function(evt) {
            this.contentDocument.defaultView.__resizeTrigger__ = this.__resizeElement__;
            this.contentDocument.defaultView.addEventListener('resize', EleResize._handleResize);
        }
    };
    if (document.attachEvent) { //ie9-10
        EleResize.on = function(ele, handler, context) {
            var handlers = ele.__z_resizeListeners;
            if (!handlers) {
                handlers = [];
                ele.__z_resizeListeners = handlers;
                ele.__resizeTrigger__ = ele;
                ele.attachEvent('onresize', EleResize._handleResize);
            }
            handlers.push({
                handler: handler,
                context: context
            });
        };
        EleResize.off = function(ele, handler, context) {
            var handlers = ele.__z_resizeListeners;
            if (handlers) {
                EleResize._removeHandler(ele, handler, context);
                if (handlers.length === 0) {
                    ele.detachEvent('onresize', EleResize._handleResize);
                    delete ele.__z_resizeListeners;
                }
            }
        }
    } else {
        EleResize.on = function(ele, handler, context) {
            var handlers = ele.__z_resizeListeners;
            if (!handlers) {
                handlers = [];
                ele.__z_resizeListeners = handlers;

                if (getComputedStyle(ele, null).position === 'static') {
                    ele.style.position = 'relative';
                }
                var obj = EleResize._createResizeTrigger(ele);
                ele.__resizeTrigger__ = obj;
                obj.__resizeElement__ = ele;
            }
            handlers.push({
                handler: handler,
                context: context
            });
        };
        EleResize.off = function(ele, handler, context) {
            var handlers = ele.__z_resizeListeners;
            if (handlers) {
                EleResize._removeHandler(ele, handler, context);
                if (handlers.length === 0) {
                    var trigger = ele.__resizeTrigger__;
                    if (trigger) {
                        trigger.contentDocument.defaultView.removeEventListener('resize', EleResize._handleResize);
                        ele.removeChild(trigger);
                        delete ele.__resizeTrigger__;
                    }
                    delete ele.__z_resizeListeners;
                }
            }
        }
    }

    return EleResize;
}));

(function(root, factory) {

    'use strict';

    if (typeof define === 'function' && define.amd) {
        define(factory);
    } else if (typeof exports !== 'undefined') {
        module.exports = factory();
    } else {
        root.yytDragResize = factory();
    }

}(this, function() {


    /**
     * 拖拽改变大小
     * @param oParent 需要改变大小的element
     * @param handle  可拖拽的handle
     * @param isLeft
     * @param isTop
     * @param lockX
     * @param lockY
     */
    var dragMinWidth = 250;
    var dragMinHeight = 124;

    function dragResize(oParent, handle, isLeft, isTop, lockX, lockY) {

        var disX, disY, iParentTop, iParentLeft, iParentWidth, iParentHeight;

        // 拖拽移动
        function onMouseMove(event) {
            var event = event || window.event;
            var iL = event.clientX - disX;
            var iT = event.clientY - disY;
            var maxW = document.documentElement.clientWidth - oParent.offsetLeft - 2;
            var maxH = document.documentElement.clientHeight - oParent.offsetTop - 2;
            var iW = isLeft ? iParentWidth - iL : iParentWidth + iL;
            var iH = isTop ? iParentHeight - iT : iParentHeight + iT;
            isLeft && (oParent.style.left = iParentLeft + iL + "px");
            isTop && (oParent.style.top = iParentTop + iT + "px");
            iW < dragMinWidth && (iW = dragMinWidth);
            iW > maxW && (iW = maxW);
            lockX || (oParent.style.width = iW + "px");
            iH < dragMinHeight && (iH = dragMinHeight);
            iH > maxH && (iH = maxH);
            lockY || (oParent.style.height = iH + "px");
            if ((isLeft && iW == dragMinWidth) || (isTop && iH == dragMinHeight)) document.onmousemove = null;
            return false;
        }

        function onMouseUp() {
            // 取消事件绑定
            // $(document).off('mousemove', onMouseMove);
            // $(document).off('mouseup', onMouseUp);
            $(document)
                .unbind('mousemove', onMouseMove)
                .unbind('mouseup', onMouseUp);
        }

        function onMouseDown(event) {
            var event = event || window.event;
            disX = event.clientX;
            disY = event.clientY;
            iParentTop = oParent.offsetTop;
            iParentLeft = oParent.offsetLeft;
            iParentWidth = oParent.offsetWidth;
            iParentHeight = oParent.offsetHeight;

            // 绑定事件
            $(document).mousemove(onMouseMove);
            $(document).mouseup(onMouseUp);

            return false;
        }

        $(handle).mousedown(onMouseDown);
    }

    return dragResize;
}));
/**
 * 消息类工具
 * 参考uft.Utils
 */
(function(root, factory) {

    'use strict';

    if (typeof define === 'function' && define.amd) {
        define(factory);
    } else if (typeof exports !== 'undefined') {
        module.exports = factory();
    } else {
        root.yytMessage = root.yytMsg = factory();
    }

}(this, function() {
    function initStyle() {
        var nod = document.createElement('style'),
            str = '.move-up-appear {\n' +
            '    -webkit-animation-duration: .3s;\n' +
            '    animation-duration: .3s;\n' +
            '    -webkit-animation-fill-mode: both;\n' +
            '    animation-fill-mode: both;\n' +
            '    -webkit-animation-play-state: paused;\n' +
            '    animation-play-state: paused\n' +
            '}\n' +
            '\n' +
            '.move-up-appear {\n' +
            '    -webkit-animation-name: yytMoveUpIn;\n' +
            '    animation-name: yytMoveUpIn;\n' +
            '    -webkit-animation-play-state: running;\n' +
            '    animation-play-state: running\n' +
            '}\n' +
            '\n' +
            '@-webkit-keyframes yytMoveUpIn {\n' +
            '    0% {\n' +
            '        -webkit-transform-origin: 0 0;\n' +
            '        transform-origin: 0 0;\n' +
            '        -webkit-transform: translateY(-100%);\n' +
            '        transform: translateY(-100%);\n' +
            '        opacity: 0\n' +
            '    }\n' +
            '\n' +
            '    100% {\n' +
            '        -webkit-transform-origin: 0 0;\n' +
            '        transform-origin: 0 0;\n' +
            '        -webkit-transform: translateY(0);\n' +
            '        transform: translateY(0);\n' +
            '        opacity: 1\n' +
            '    }\n' +
            '}\n' +
            '\n' +
            '@keyframes yytMoveUpIn {\n' +
            '    0% {\n' +
            '        -webkit-transform-origin: 0 0;\n' +
            '        transform-origin: 0 0;\n' +
            '        -webkit-transform: translateY(-100%);\n' +
            '        transform: translateY(-100%);\n' +
            '        opacity: 0\n' +
            '    }\n' +
            '\n' +
            '    100% {\n' +
            '        -webkit-transform-origin: 0 0;\n' +
            '        transform-origin: 0 0;\n' +
            '        -webkit-transform: translateY(0);\n' +
            '        transform: translateY(0);\n' +
            '        opacity: 1\n' +
            '    }\n' +
            '}\n' +
            '\n' +
            '.yyt-message {\n' +
            '    font-size: 12px;\n' +
            '    position: fixed;\n' +
            '    z-index: 2010;\n' +
            '    width: 100%;\n' +
            '    top: 24px;\n' +
            '    left: 0;\n' +
            '    pointer-events: none;\n' +
            '}\n' +
            '\n' +
            '.yyt-message-notice {\n' +
            '    padding: 8px;\n' +
            '    text-align: center;\n' +
            '    -webkit-transition: height .3s ease-in-out, padding .3s ease-in-out;\n' +
            '    transition: height .3s ease-in-out, padding .3s ease-in-out\n' +
            '}\n' +
            '\n' +
            '.yyt-message-notice:first-child {\n' +
            '    margin-top: -8px\n' +
            '}\n' +
            '\n' +
            '.yyt-message-notice-close {\n' +
            '    position: absolute;\n' +
            '    right: 4px;\n' +
            '    top: 10px;\n' +
            '    color: #999;\n' +
            '    outline: 0\n' +
            '}\n' +
            '\n' +
            '.yyt-message-notice-close i.yyt-icon {\n' +
            '    font-size: 22px;\n' +
            '    color: #999;\n' +
            '    -webkit-transition: color .2s ease;\n' +
            '    transition: color .2s ease;\n' +
            '    position: relative;\n' +
            '    top: -3px\n' +
            '}\n' +
            '\n' +
            '.yyt-message-notice-close i.yyt-icon:hover {\n' +
            '    color: #444\n' +
            '}\n' +
            '\n' +
            '.yyt-message-notice-content {\n' +
            '    display: inline-block;\n' +
            '    pointer-events: all;\n' +
            '    padding: 8px 16px;\n' +
            '    border-radius: 4px;\n' +
            '    -webkit-box-shadow: 0 1px 6px rgba(0, 0, 0, .2);\n' +
            '    box-shadow: 0 1px 6px rgba(0, 0, 0, .2);\n' +
            '    background: #fff;\n' +
            '    position: relative;\n' +
            '}\n' +
            '.yyt-message [type="error"] .yyt-message-notice-content{ border:1px solid #ffacac;}\n' +
            '.yyt-message [type="success"] .yyt-message-notice-content{ border:1px solid #97ed91;}\n' +
            '.yyt-message [type="warn"] .yyt-message-notice-content{ border:1px solid #ff9301;}\n' +
            '.yyt-message [type="info"] .yyt-message-notice-content{ border:1px solid #2d8cf0;}\n' +
            '\n' +
            '.yyt-message-notice-content-text {\n' +
            '    display: inline-block;' +
            '    word-break: break-word;position:relative;\n' +
            '}\n' +
            '\n' +
            '.yyt-message-notice-closable .yyt-message-notice-content-text {\n' +
            '    padding-right: 32px\n' +
            '}\n' +
            '.yyt-message-custom-content{' +
            '    max-height: 250px;\n' +
            '    overflow: auto;    padding-right: 20px; padding-left:20px;}' +
            '.yyt-message-notice-content-text .close{' +
            '  cursor:pointer;opacity: .8;vertical-align: middle;margin-left: 15px;\n' +
            '    margin-top: 3px;\n' +
            '    width: 12px;position: absolute;\n' +
            '    right: 0;\n' +
            '    top: 0;' +
            '}' +
            '\n' +
            '.yyt-message-success.fa {\n' +
            '    color: #19be6b\n' +
            '}\n' +
            '\n' +
            '.yyt-message-error.fa {\n' +
            '    color: #ed4014\n' +
            '}\n' +
            '\n' +
            '.yyt-message-warning.fa {\n' +
            '    color: #f90\n' +
            '}\n' +
            '\n' +
            '.yyt-message-info.fa {\n' +
            '    color: #2d8cf0\n' +
            '}\n' +
            '\n' +
            '.yyt-message .fa {\n' +
            '    margin-right: 4px;\n' +
            '    font-size: 16px;\n' +
            '    vertical-align: middle\n' +
            '}' +
            '.yyt-badge{position: relative;display: inline-block;}\n' +
            '.yyt-badge .yyt-badge-count{\n' +
            '\tfont-family: Monospaced Number;\n' +
            '    line-height: 1;\n' +
            '    vertical-align: middle;\n' +
            '    min-width: 20px;\n' +
            '    color: #fff;\n' +
            '    line-height: 18px;\n' +
            '    text-align: center;\n' +
            '    padding: 0 6px;\n' +
            '    font-size: 12px;\n' +
            '    white-space: nowrap;\n' +
            '    -webkit-transform-origin: -10% center;\n' +
            '    transform-origin: -10% center;\n' +
            '    z-index: 10;\n' +
            '    box-shadow: 0 0 0 1px #fff;\n' +
            '    height: 18px;\n' +
            '    border-radius: 9px;\n' +
            '    background: #fff5f5;color: #fa795e;display:inline-block;}' +
            '.yyt-badge .yyt-badge-count:before{' +
            '    content: "+";\n' +
            '    position: relative;\n' +
            '    top: -1px;\n' +
            '    margin: 0 1px;' +
            '}';


        nod.type = 'text/css';
        if (nod.styleSheet) { //ie下
            nod.styleSheet.cssText = str;
        } else {
            nod.innerHTML = str;
        }
        $('head').append(nod);
    }

    // 渲染样式
    initStyle();

    /**
     * 获取msg的img
     * @param type
     * @returns {string}
     */
    function getMsgHtmlByType(type, id, msg) {
        var IMG = {
            success: '',
            info: '',
            warn: '',
            error: ''
        };
        return IMG[type] || IMG.info
    }

    var count = 0;
    var errorCount = 0;
    var equalErrorMsg = 0; //相同错误消息
    var prevErrorMsg = ''; //上一条错误消息

    /**
     * 提示工具
     * @param msg
     * @param config
     */
    function yytMsg(msg, config) {
        config.isClose = config.isClose || false; //是否显示关闭按钮
        config.autoClose = typeof config.autoClose == 'boolean' ? config.autoClose : true; //自动关闭 默认开启
        //如果显示关闭按钮  自动关闭就不开启
        if (config.isClose) {
            config.autoClose = false;
        }
        var $el = $('.yyt-message');
        if ($el.length == 0) {
            $('body').append('<div id="yyt-message" class="yyt-message"></div>')
        }

        function createMoreMsg(count) {
            if ($(".over-error-tip").hasClass("return")) return;
            var html = '';
            html += '<p class="over-error-tip" style="pointer-events: initial;color: #57a3f3;text-align: center;cursor: pointer;margin: 5px 0">查看所有消息';
            if (count > 0) {
                html += '<span>(' + count + ')</span>';
            }
            html += '</p>';
            if ($el.find(".over-error-tip").length > 0) {
                $el.find(".over-error-tip").replaceWith(html);
            } else {
                $el.append(html);
            }

            $(".over-error-tip").off("click").on("click", function() {
                var _this = this;
                $(this).addClass("return");
                var afterErrorDom = $(this).siblings("div:hidden");
                afterErrorDom.each(function(index, ele) {
                    $(ele).show();
                });
                $(_this).hide();
            })
        }

        var id = Date.parse(new Date()) + '_' + count;
        config = config || {};
        if (config.type == 'error') {
            if (config.isMerge && config.isClose) {
                if (prevErrorMsg == msg) {
                    equalErrorMsg++;
                } else {
                    equalErrorMsg = 0;
                }
                prevErrorMsg = msg;
            }
            if (config.traceId) {
                msg = msg.replace("${traceId}", ',traceId:' + config.traceId);
            }
        }
        var html = '<div class="yyt-message-notice"  >' +
            '            <div class="yyt-message-notice-content move-up-appear">\n' +
            '                <div class="yyt-message-notice-content-text">\n' +
            '                    <div class="yyt-message-custom-content">\n' +
            '                        <img class="info-img" style=" position: absolute;left: 0;top: 3px;vertical-align: middle;margin-right: 5px;margin-top: -2px;" width="16" src="' + getMsgHtmlByType(config.type) + '"/>' +
            '                        <span>' + msg + '</span>\n';
        if (config.isClose)
            html += '<img class="close" src="" />';
        html += '                    </div>\n' +
            '                </div>\n' +
            '            </div>' +
            '       </div>';
        var isEqualError = config.type == 'error' && equalErrorMsg > 0 && config.isMerge; //是否合并相同错误信息
        var isHidden = errorCount >= 5 && config.type == 'error' && !$(".over-error-tip").hasClass("return"); //判断超出5条错误数据 隐藏
        //连续相同的错误信息 不插入到容器中
        if (!isEqualError) {
            $('#yyt-message').append('<div type="' + (config.type || '') + '"  id="' + id + '" ' + (isHidden ? 'style="display:none"' : '') + '>' + html + '</div>');
            // 判断错误类型 增加错误条数
            if (config.type == 'error') {
                errorCount++;
            }
        }
        var errorMsgDom = $("#yyt-message").children("div[type='error']:last"); //获取最后一条错误信息
        //给相同的错误信息 设置相同错误信息条数
        if (equalErrorMsg > 0 && config.isMerge) {
            if (errorMsgDom.find(".yyt-message-notice-content .yyt-badge").length == 0) {
                errorMsgDom.find(".yyt-message-notice-content .close").before('<span class="yyt-badge"> <span class="yyt-badge-count">' + equalErrorMsg + '</span></span>');
            } else {
                errorMsgDom.find(".yyt-message-notice-content .yyt-badge-count").text(equalErrorMsg);
            }
        }
        if (errorCount > 5 && config.type == 'error') {
            createMoreMsg(errorCount - 5); //错误信息超过5条 创建更多消息
        }

        if (config.autoClose) {
            var $el = $('#' + id);
            setTimeout(function() {
                $el.remove();
            }, config.delay || 4000);
        } else {
            $('#' + id).on('click', '.close', function(e) {
                var msgDom = $("#" + id);
                var type = msgDom.attr("type");
                if (type == 'error') {
                    var hideErrorDom = $(".over-error-tip").siblings("div:hidden").eq(0);
                    $('#yyt-message').find(".over-error-tip").before(hideErrorDom.clone(true).show());
                    hideErrorDom.remove();
                    errorCount--;
                    createMoreMsg(errorCount - 5);
                    if (errorCount <= 5) {
                        $(".over-error-tip").remove();
                    }
                    prevErrorMsg = '';
                }
                msgDom.remove();
            });
        }
        count++;
        return $('#' + id);

    }

    // 警告消息
    yytMsg.showWarnMsg = function(msg, config) {
        var conf = config || {};
        conf.type = 'warn';
        yytMsg(msg, conf);
    };
    // 错误消息
    yytMsg.showErrorMsg = function(msg, config) {
        var conf = config || {};
        conf.type = 'error';
        conf.isMerge = true;
        conf.isClose = conf.isClose === false ? false : true; //默认开启错误消息关闭按钮
        return yytMsg(msg, conf);
    };
    // 信息
    yytMsg.showInfoMsg = function(msg, config) {
        var conf = config || {};
        conf.type = 'info';
        yytMsg(msg, conf);
    };
    //成功消息
    yytMsg.showSuccessMsg = function(msg, config) {
        var conf = config || {};
        conf.type = 'success';
        yytMsg(msg, conf);
    };
    // 处理中消息
    yytMsg.showProcessMsg = function(msg, config) {

    };

    // 提示消息
    yytMsg.showAlertMsg = function(msg, config) {

    };

    function isIELowLv() {
        var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串
        var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1; //判断是否IE<11浏览器
        if (isIE) {
            var reIE = new RegExp("MSIE (\\d+\\.\\d+);");
            reIE.test(userAgent);
            var fIEVersion = parseFloat(RegExp["$1"]);
            if (fIEVersion == 8 || fIEVersion == 9) {
                return true;
            } else {
                return false
            }
        }
        return false
    }

    /**
     * 确认信息
     * @param config
     * @param config.title 标题
     * @param config.content 内容
     * @param config.confirm 确认回调
     */
    yytMsg.showConfirmMsg = function(config) {
        var elId = Date.parse(new Date());
        config = config ? config : {};
        var confirmBtnText = config.confirmBtnText || '确定',
            cancelBtnText = config.cancelBtnText || '取消';
        var modal = $.yyt_modal({
            closeIsDestory: true,
            target: config.target || '#yyt-msg', //modify by xiezf 增加消息的指向 防止被其它相同变量污染
            keyboard: true,
            enableClose: true,
            cssclass: 'yyt-confirm-wrap ' + (isIELowLv() ? 'is-low-IE' : ''),
            title: config.title || '',
            content: '<div class="yyt-confirm-content">' + (config.content || '') + '</div>' +
                '<div class="yyt-modal-footer" id="foot-' + elId + '">' +
                '<button class="yyt-btn cancel" data-dismiss="modal" style="margin-right: 10px">' + cancelBtnText + '</button> ' +
                '<button class="yyt-btn yyt-btn-primary confirm">' + confirmBtnText + '</button>' +
                '</div>'
        });
        modal.render();
        $('body').on('click', "#foot-" + elId + " .confirm", function() {
            if (typeof config.confirm == 'function') {
                var result = config.confirm.call(this, modal);
                if (result !== false) {
                    modal.destroy();
                }
            }
        });
        $('body').on('keydown', function(e) {
            if (e.keyCode == 13)
                $('body').find("#foot-" + elId + " .confirm").trigger('click');
        });
        $('body').on('click', "#foot-" + elId + " .cancel", function() {
            if (typeof config.cancel == 'function') {
                config.cancel.call(this, modal)
            }
            modal.destroy();
        });
        return modal;
    };
    // 等待
    yytMsg.showLoading = function(el, config) {
        //className
        if (config) {
            if (config.fixed && $('body').hasClass('spin-wrap')) {
                return;
            }
        }
        if ($(el).hasClass('spin-wrap'))
            return;

        // 初始化配置参数
        var setting = {
            isShowIcon: true,
            text: '',
            fixed: false
        };
        for (var key in config) {
            if (config[key] !== undefined)
                setting[key] = config[key];
        }
        var html = '<div id="loading-wrap" class="loading-wrap ' + (setting.className || '') + '">';

        html += '<div class="spin-main">';
        if (setting.isShowIcon) {
            /*新loading效果*/
            html += '<img class="spin-main-img" src="">'
            /*旧的loading效果*/
            // html += '<img class="spin-main-img" src="">';
        }
        if (setting.text) {
            html += '<p class="spin-loading-text">' + setting.text + '</p></div>'
        }
        html += '</div></div>';
        //不固定
        if (!setting.fixed) {
            $(el).addClass('spin-wrap');
            $(el).append(html);
            $('.spin-main').css('position', 'absolute');
        } else {
            //固定
            $('body').addClass('spin-wrap');
            $('body').append(html);
        }
    };

    // 取消loading
    yytMsg.hideAllLoading = function(el) {
        if (el) {
            if (!$(el).hasClass('spin-wrap')) {
                $('body').removeClass('spin-wrap');
                $('body').children('#loading-wrap').remove()
            } else {
                $(el).removeClass('spin-wrap');
                $(el).children('#loading-wrap').remove()
            }
        }
    };
    yytMsg.stopLoading = yytMsg.hideAllLoading;


    //显示遮罩
    yytMsg.showMask = function(el, config) {
        if (!config) config = {};
        config.isShowIcon = false; //不显示loadingIcon
        yytMsg.showLoading(el, config)
    };

    //停止显示遮罩
    yytMsg.stopMask = function(el) {
        yytMsg.stopLoading(el);
    };

    //清除所有消息弹框
    yytMsg.clearMsg = function() {
        var yytMessageWrap = $("#yyt-message");
        var yytMessageList = yytMessageWrap.children("div")
        for (var i = 0; i < yytMessageList.length; i++) {
            if ($(yytMessageList[i]).find(".close").length !== 0) {
                $(yytMessageList[i]).find(".close").trigger("click");
            } else {
                $(yytMessageList[i]).remove();
            }
        }
    }


    return yytMsg;
}));
/**
 * ajax请求工具
 */
(function(root, factory) {

    'use strict';

    if (typeof define === 'function' && define.amd) {
        define(factory);
    } else if (typeof exports !== 'undefined') {
        module.exports = factory();
    } else {
        root.yytAjax = factory();
    }

}(this, function() {
    var messageUtil = {};

    if (window && window.yytMsg) {
        messageUtil = window.yytMsg;
    } else {
        messageUtil.showErrorMsg = $.noop();
    }
    var isYytPlatform = true; //默认是新平台
    if (window.Constants) {
        isYytPlatform = typeof window.Constants.isYytPlatform == 'boolean' ? window.Constants.isYytPlatform : true;
    }
    /**
     * ajax请求
     * @param config
     * @param successFunc
     * @param errorFunc
     */
    function doAjax(config, successFunc, errorFunc) {
        if (!config) config = {};
        //是否异步
        var type = true;
        if (config.async === false) {
            type = false
        }
        //获取funCode
        var funCode = yytUrl.getUrlParam('funCode');
        //是否显示默认提示
        var isTip = typeof config.isTip == 'boolean' ? config.isTip : true;
        if (config.url.indexOf("http") == -1) {
            config.url = yytUrl.getContextPath() + config.url
        }
        var data = {};
        // processParams 处理参数 true 处理 false 不处理 默认:true
        // processData 处理数据 true 处理 false 不处理 默认: true
        var processParams = typeof config.processParams == 'boolean' ? config.processParams : true;
        var processData = typeof config.processData == 'boolean' ? config.processData : true;
        if (processParams) {
            data = {
                _JSONPARA: JSON.stringify(config.params || {}),
                funCode: funCode
            };
        } else {
            data = config.params;
        }
        // 旧平台不发 新平台发 isYytPlatform true:新平台 false:旧平台
        //是否发送错误日志 默认为true
        var sendErrorMsg = false;
        if (true) {
            sendErrorMsg = typeof config.sendErrorMsg == 'boolean' ? config.sendErrorMsg : true;
        }
        config.sendErrorMsg = sendErrorMsg;
        return $.ajax({
            type: config.type || config.method || 'GET',
            cache: (!config.cache && config.cache !== false) ? false : config.cache, //modify by xiezf IE浏览器下 请求会走缓存,统一处理
            async: type,
            data: data,
            dataType: config.dataType || 'json',
            url: config.url,
            success: function(res) {
                var result = res;
                //如果不处理数据 直接抛出数据
                if (!processData) {
                    if (typeof config.onSuccess == 'function') {
                        config.onSuccess(result);
                    }
                    if (typeof successFunc == 'function') {
                        return successFunc(result);
                    }
                    return;
                }
                if (typeof res == 'string') {
                    try {
                        var temp = JSON.parse(res);
                        result = temp;
                    } catch (e) {}
                }
                if (!result) {
                    if (typeof config.onFailure == 'function') {
                        config.onFailure.call(this, result);
                    }
                    if (typeof errorFunc == 'function')
                        errorFunc(result);
                } else if (!result.success) {
                    if (typeof config.onFailure == 'function') {
                        config.onFailure.call(this, result);
                    }
                    if (isTip) {
                        // 全局可能问题比较麻烦
                        if (yytAjax.extend && typeof yytAjax.extend.sendMsgError == 'function') {
                            yytAjax.extend.sendMsgError({
                                errMsg: result.msg,
                                config: config,
                                params: result
                            });
                        } else {
                            messageUtil.showErrorMsg(res.msg || "请求出错，请联系管理员");
                        }

                    }
                    if (typeof errorFunc == 'function')
                        errorFunc(result);
                } else {
                    if (typeof config.onSuccess == 'function')
                        config.onSuccess(result.data || result.datas);
                    if (typeof successFunc == 'function')
                        return successFunc(result.data || result.datas);
                }
            },
            error: function(err) {
                if (typeof config.onFailure == 'function') {
                    config.onFailure.call(this, err);
                }
                if (isTip)
                    if (yytAjax.extend && typeof yytAjax.extend.sendMsgError == 'function') {
                        yytAjax.extend.sendMsgError({
                            errMsg: err.msg,
                            config: config,
                            params: err
                        });
                    } else {
                        messageUtil.showErrorMsg("请求出错，请联系管理员");
                    }


                if (typeof errorFunc == 'function')
                    return errorFunc(err);
            },
            complete: function(res) {
                // if(window.yytAjax && typeof window.yytAjax.afterAjaxComplete == 'function'){
                //     window.yytAjax.afterAjaxComplete(arguments);
                // }
                var server = res.getResponseHeader('server');
                if (server && server.indexOf('WebSEAL') != -1) {
                    yytUtil.msg.showConfirmMsg({
                        content: '请求超时，是否刷新页面？',
                        title: '提示',
                        confirm: function(modal) {
                            window.top.location.reload();
                            modal.close();
                        }
                    });
                }
                typeof config.onComplete == 'function' && config.onComplete.call(this, res);
            }
        });
    }

    function yytAjax(config) {
        $.extend(config || {}, {
            isYytPlatform: isYytPlatform
        }); //传入isYytPlatform
        if (config.async === false) {
            //同步
            return yytAjax.doAsyncRequest(config.url, config.params, config.onSuccess, config.onFailure, config.onComplete, config)
        } else {
            //异步
            return yytAjax.require(config)
        }
    }


    /**
     * ajax请求
     * @param config
     */
    yytAjax.require = function(config) {
        var deferred = $.Deferred();
        doAjax(config, deferred.resolve, deferred.reject);
        return deferred.promise();
    };

    /**
     * 调用服务
     * @param serviceConfig
     * @param serviceConfig.config
     * @param serviceConfig._SNAME
     * @param serviceConfig._METHOD
     * @param serviceConfig.params
     * @return {*}
     */
    yytAjax.callServer = function(serviceConfig) {
        var config = serviceConfig.config || {};
        var basePath = yytPlatformUtils.getAppPathByUrl();

        var servicePath = '/YytServiceDispatch?_SNAME=' + serviceConfig._SNAME + '&_METHOD=' + serviceConfig._METHOD;
        var url = basePath + servicePath;

        if (config.async === false) {
            //同步
            return yytAjax.doAsyncRequest(url, serviceConfig.params, config.onSuccess, config.onFailure, config.onComplete, config)
        } else {
            //异步
            return yytAjax.require(yytUtil.deepApply({
                url: url,
                params: serviceConfig.params
            }, config));
        }
    };

    /**
     * 同步请求
     * @param url
     * @param params
     * @param onSuccess
     * @param onFailure
     * @param onComplete
     */
    yytAjax.doAsyncRequest = function(url, params, onSuccess, onFailure, onComplete, conf) {
        var config = {
            url: url,
            params: params,
            async: false,
            onSuccess: onSuccess,
            onFailure: onFailure,
            onComplete: onComplete,
            type: conf.type || conf.method || 'GET',
            //是否显示默认提示
            isTip: 'isTip' in conf ? conf.isTip : true
        };
        var http = doAjax(config);
        // 执行回调
        if (http.responseText) {
            try {
                var json = JSON.parse(http.responseText);
                return json;
            } catch (e) {
                if (config.params && config.params.isThrowException && config.params.isThrowException === true) {
                    messageUtil.showErrorMsg(e);
                    throw e;
                }
            }
            return http.responseText;
        }

        return http
    };
    /**
     * 异步请求
     * @param url
     * @param params
     * @param onSuccess
     * @param onFailure
     * @param onComplete
     */
    // yytAjax.doSyncRequest = function doSyncRequest(url, params, onSuccess, onFailure, onComplete) {
    //     var config = {
    //         url: url,
    //         params: params,
    //         async: false,
    //         onSuccess: onSuccess,
    //         onFailure: onFailure,
    //         onComplete: onComplete
    //     };
    //     return yytAjax.require(config, onSuccess, onFailure, onComplete);
    //
    // };
    yytAjax.post = function(config) {
        config.method = 'POST';
        return yytAjax.require(config)
    };

    /**
     * 获取请求上下文路径
     * @ param {Boolean} disContainApp 不包含app路径
     */
    function getAppPathByUrl(disContainApp) {
        //当前页面
        var curTotalPath = window.top.document.location.href;

        //当前页面路径
        var pathName = window.top.document.location.pathname;

        //当前页面路径起始位置
        var pathNamePos = curTotalPath.indexOf(pathName);

        //host
        var hostPath = curTotalPath.substring(0, pathNamePos);

        //工程名
        var paths = pathName.split('/');
        paths.length = paths.length - 1;

        if (paths.length <= 0) {
            return hostPath;
        } else {
            var appPath = paths[0];
            var objectNameList = [];
            for (var i = 0; i < paths.length; i++) {
                objectNameList.push(paths[i]);
                if (paths[i] == 'yytcloud') {
                    appPath += '/' + paths[i];
                    continue;
                }
                if (paths[i].indexOf('yyt') != -1) {
                    //不要应用名
                    if (!disContainApp) {
                        appPath = objectNameList.join('/');
                    }
                    break;
                }
            }
            return hostPath + appPath;
        }
    }

    /**
     * @Deprecated 要区分promise和jquery太为难了, 使用yytAjax.require
     * @param config
     * @return jQuery.Promise
     */
    yytAjax.requireWithPromise = function(config) {
        if (window.Promise !== undefined) {
            var promise = new Promise(function(resolve, reject) {
                doAjax(config, resolve, reject)
            });
            return promise;
        } else {
            return yytAjax.require(config);
        }
    };

    /**
     * @Deprecated 要区分promise和jquery太为难了, 使用yytAjax.server
     * @param serviceConfig
     */
    yytAjax.requireService = function(serviceConfig) {
        var config = serviceConfig.config || {};
        var basePath = yytPlatformUtils.getAppPathByUrl();

        var servicePath = '/YytServiceDispatch?_SNAME=' + serviceConfig.servicename + '&_METHOD=' + serviceConfig.method;
        var url = basePath + servicePath;

        if (config.async === false) {
            //同步
            return yytAjax.doAsyncRequest(url, serviceConfig.params, config.onSuccess, config.onFailure, config.onComplete, config)
        } else {
            //异步
            return yytAjax.requireWithPromise(yytUtil.deepApply({
                url: url,
                params: serviceConfig.params
            }, config))
        }
    };


    // yytAjax.ajax = $.ajax;

    return yytAjax;
}));

var Uft = {};

Uft.isIE = function() {
    var ua = navigator.userAgent.toLowerCase(),
        check = function(r) {
            return r.test(ua);
        },
        isOpera = check(/opera/);
    return !isOpera && check(/msie/);
}();

Uft.toString = Object.prototype.toString;

/**
 * Copies all the properties of config to obj.
 * @param {Object} obj The receiver of the properties
 * @param {Object} config The source of the properties
 * @param {Object} defaults A different object that will also be applied for default values
 * @return {Object} returns obj
 * @member Uft apply
 */
Uft.apply = function(o, c, defaults) {
    // no "this" reference for friendly out of scope calls
    if (defaults) {
        Uft.apply(o, defaults);
    }
    if (o && c && typeof c == 'object') {
        for (var p in c) {
            o[p] = c[p];
        }
    }
    return o;
};

/**
 * Creates namespaces to be used for scoping variables and classes so that they are not global.
 * Specifying the last node of a namespace implicitly creates all other nodes. Usage:
 * <pre><code>
 Uft.namespace('Company', 'Company.data');
 Uft.namespace('Company.data'); // equivalent and preferable to above syntax
 Company.Widget = function() { ... }
 Company.data.CustomStore = function(config) { ... }
 </code></pre>
 * @param {String} namespace1
 * @param {String} namespace2
 * @param {String} etc
 * @return {Object} The namespace object. (If multiple arguments are passed, this will be the last namespace created)
 * @method namespace
 */
Uft.namespace = function() {
    var o, d;
    Uft.each(arguments, function(v) {
        d = v.split(".");
        o = window[d[0]] = window[d[0]] || {};
        Uft.each(d.slice(1), function(v2) {
            o = o[v2] = o[v2] || {};
        });
    });
    return o;
};

Uft.ns = Uft.namespace;


/**
 * <p>Extends one class to create a subclass and optionally overrides members with the passed literal. This method
 * also adds the function "override()" to the subclass that can be used to override members of the class.</p>
 * For example, to create a subclass of Chart:
 * <pre><code>
 MyChart = Uft.extend(Chart, {
constructor: function(config) {

//Create configuration for this Grid.
var store = new chart.Store({...});
var colModel = new chart.ColumnModel({...});

//Create a new config object containing our computed properties
//*plus* whatever was in the config parameter.
config = Ext.apply({
    store: store,
    colModel: colModel
}, config);

MyChart.superclass.constructor.call(this, config);

//Your postprocessing here
},

yourMethod: function() {
// etc.
}
});
 </code></pre>
 *
 * <p>This function also supports a 3-argument call in which the subclass's constructor is
 * passed as an argument. In this form, the parameters are as follows:</p>
 * <div class="mdetail-params"><ul>
 * <li><code>subclass</code> : Function <div class="sub-desc">The subclass constructor.</div></li>
 * <li><code>superclass</code> : Function <div class="sub-desc">The constructor of class being extended</div></li>
 * <li><code>overrides</code> : Object <div class="sub-desc">A literal with members which are copied into the subclass's
 * prototype, and are therefore shared among all instances of the new class.</div></li>
 * </ul></div>
 *
 * @param {Function} superclass The constructor of class being extended.
 * @param {Object} overrides <p>A literal with members which are copied into the subclass's
 * prototype, and are therefore shared between all instances of the new class.</p>
 * <p>This may contain a special member named <tt><b>constructor</b></tt>. This is used
 * to define the constructor of the new class, and is returned. If this property is
 * <i>not</i> specified, a constructor is generated and returned which just calls the
 * superclass's constructor passing on its parameters.</p>
 * <p><b>It is essential that you call the superclass constructor in any provided constructor. See example code.</b></p>
 * @return {Function} The subclass constructor from the <code>overrides</code> parameter, or a generated one if not provided.
 */
Uft.extend = function() {
    // inline overrides
    var io = function(o) {
        for (var m in o) {
            this[m] = o[m];
        }
    };
    var oc = Object.prototype.constructor;

    return function(sb, sp, overrides) {
        if (typeof sp == 'object') {
            overrides = sp;
            sp = sb;
            sb = overrides.constructor != oc ? overrides.constructor : function() {
                sp.apply(this, arguments);
            };
        }
        var F = function() {},
            sbp,
            spp = sp.prototype;

        F.prototype = spp;
        sbp = sb.prototype = new F();
        sbp.constructor = sb;
        sb.superclass = spp;
        if (spp.constructor == oc) {
            spp.constructor = sp;
        }
        sb.override = function(o) {
            Uft.override(sb, o);
        };
        sbp.superclass = sbp.supr = (function() {
            return spp;
        });
        sbp.override = io;
        Uft.override(sb, overrides);
        sb.extend = function(o) {
            return Uft.extend(sb, o);
        };
        return sb;
    };
}();



/**
 * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
 * Usage:<pre><code>
 Uft.override(MyClass, {
newMethod1: function(){
// etc.
},
newMethod2: function(foo){
// etc.
}
});
 </code></pre>
 * @param {Object} origclass The class to override
 * @param {Object} overrides The list of functions to add to origClass.  This should be specified as an object literal
 * containing one or more methods.
 * @method override
 */
Uft.override = function(origclass, overrides) {
    if (overrides) {
        var p = origclass.prototype;
        Uft.apply(p, overrides);
        if (Uft.isIE && overrides.hasOwnProperty('toString')) {
            p.toString = overrides.toString;
        }
    }
};

/**
 * Iterates an array calling the supplied function.
 * @param {Array/NodeList/Mixed} array The array to be iterated. If this
 * argument is not really an array, the supplied function is called once.
 * @param {Function} fn The function to be called with each item. If the
 * supplied function returns false, iteration stops and this method returns
 * the current <code>index</code>. This function is called with
 * the following arguments:
 * <div class="mdetail-params"><ul>
 * <li><code>item</code> : <i>Mixed</i>
 * <div class="sub-desc">The item at the current <code>index</code>
 * in the passed <code>array</code></div></li>
 * <li><code>index</code> : <i>Number</i>
 * <div class="sub-desc">The current index within the array</div></li>
 * <li><code>allItems</code> : <i>Array</i>
 * <div class="sub-desc">The <code>array</code> passed as the first
 * argument to <code>Uft.each</code>.</div></li>
 * </ul></div>
 * @param {Object} scope The scope (<code>this</code> reference) in which the specified function is executed.
 * Defaults to the <code>item</code> at the current <code>index</code>
 * within the passed <code>array</code>.
 * @return See description for the fn parameter.
 */
Uft.each = function(array, fn, scope) {
    if (Uft.isEmpty(array, true)) {
        return;
    }
    if (!Uft.isIterable(array) || Uft.isPrimitive(array)) {
        array = [array];
    }
    for (var i = 0, len = array.length; i < len; i++) {
        if (fn.call(scope || array[i], array[i], i, array) === false) {
            return i;
        };
    }
};

/**
 * 返回第一个不为空的值。
 * <p>用法示例:第一个传入设定值, 第二个传入默认值。
 * @return 第一个不为空的值
 */
Uft.pick = function() {
    var args = arguments,
        i, arg, length = args.length;
    for (i = 0; i < length; i += 1) {
        arg = args[i];
        if (!Uft.isEmpty(arg)) {
            return arg;
        }
    }
};

/**
 * <p>Returns true if the passed value is empty.</p>
 * <p>The value is deemed to be empty if it is<div class="mdetail-params"><ul>
 * <li>null</li>
 * <li>undefined</li>
 * <li>an empty array</li>
 * <li>a zero length string (Unless the <tt>allowBlank</tt> parameter is <tt>true</tt>)</li>
 * </ul></div>
 * @param {Mixed} value The value to test
 * @param {Boolean} allowBlank (optional) true to allow empty strings (defaults to false)
 * @return {Boolean}
 */
Uft.isEmpty = function(v, allowBlank) {
    return v === null || v === undefined || ((Uft.isArray(v) && !v.length)) || (!allowBlank ? v === '' : false);
};

/**
 * 通过遍历判断数组是否为空
 */
Uft.isObjectEmpty = function(v) {
    var isEmpty = true;
    if (v) {
        for (var key in v) {
            isEmpty = false;
            return isEmpty;
        }
    }
    return isEmpty;
};

/**
 * Returns true if the passed value is a JavaScript array, otherwise false.
 * @param {Mixed} value The value to test
 * @return {Boolean}
 */
Uft.isArray = function(v) {
    return Uft.toString.apply(v) === '[object Array]';
};

Uft.isIterable = function(v) {
    //check for array or arguments
    if (Uft.isArray(v) || v.callee) {
        return true;
    }
    //check for node list type
    if (/NodeList|HTMLCollection/.test(Uft.toString.call(v))) {
        return true;
    }
    //NodeList has an item and length property
    //IXMLDOMNodeList has nextNode method, needs to be checked first.
    return ((typeof v.nextNode != 'undefined' || v.item) && Uft.isNumber(v.length));
};

/**
 * Returns true if the passed value is a JavaScript 'primitive', a string, number or boolean.
 * @param {Mixed} value The value to test
 * @return {Boolean}
 */
Uft.isPrimitive = function(v) {
    return Uft.isString(v) || Uft.isNumber(v) || Uft.isBoolean(v);
};

/**
 * Returns true if the passed value is a number. Returns false for non-finite numbers.
 * @param {Mixed} value The value to test
 * @return {Boolean}
 */
Uft.isNumber = function(v) {
    return typeof v === 'number' && isFinite(v);
};

/**
 * Returns true if the passed value is a string.
 * @param {Mixed} value The value to test
 * @return {Boolean}
 */
Uft.isString = function(v) {
    return typeof v === 'string';
};

/**
 * Returns true if the passed value is a boolean.
 * @param {Mixed} value The value to test
 * @return {Boolean}
 */
Uft.isBoolean = function(v) {
    return typeof v === 'boolean';
};

/**
 * Returns true if the passed value is an HTMLElement
 * @param {Mixed} value The value to test
 * @return {Boolean}
 */
Uft.isElement = function(v) {
    return v ? !!v.tagName : false;
};

/**
 * print infomation in console
 * @param infomation
 */
Uft.debug = function(o) {
    if (false && console && arguments && arguments.length > 0) {
        console.group(arguments[0]);
        console.trace();
        for (var i = 0; i < arguments.length; i++) {
            console.log(arguments[i]);
        }
        console.groupEnd();
    }
};



(function(root, factory) {

    'use strict';

    if (typeof define === 'function' && define.amd) {
        define(factory);
    } else if (typeof exports !== 'undefined') {
        module.exports = factory();
    } else {
        root.yytBase62 = factory();
    }

}(this, function() {
    function YYTBase62() {
        //- encode, statically
        this.encode = function(input, ibase) {
            var rtn = undefined;
            if (typeof input == 'undefined' || input == '') {
                return rtn;
            }
            var codetype = 0;
            var xtag = this.get('xtag');
            var b62x = this.get('b62x');
            var asclist = this.get('asclist');
            var ascrlist = this.get('ascrlist');
            var bpos = this.get('bpos');
            var xpos = this.get('xpos');
            var ascidx = this.get('ascidx');
            var ascmax = this.get('ascmax');
            var rb62x = fillRb62x(b62x, bpos, xpos);
            var isnum = false;
            if (ibase > 0) {
                isnum = true;
            }
            if (isnum) {
                rtn = 0;
                var num_input = xx2dec(input, ibase, rb62x);
                var obase = xpos;
                rtn = dec2xx(num_input, obase, b62x);
            } else {
                // string
                var inputArr = toUTF8Array(input); // this.str2ab(input); //input.split(''); // need '' as parameter
                var inputlen = inputArr.length;
                var setResult = this.setAscii(codetype, inputArr, ascidx, ascmax, asclist, ascrlist);
                var asctype = setResult['asctype'];
                ascidx = setResult['ascidx'];
                ascrlist = setResult['ascrlist'];
                var op = [];
                var i = 0;
                var m = 0;
                if (asctype == 1) { // ascii
                    var ixtag = xtag.charCodeAt();
                    do {
                        if (ascidx[inputArr[i]] != -1) { // why != here?
                            op[m] = xtag;
                            op[++m] = ascidx[inputArr[i]];
                        } else if (inputArr[i] == ixtag) {
                            op[m] = xtag;
                            op[++m] = xtag;
                        } else {
                            op[m] = String.fromCharCode(inputArr[i]);
                        }
                        m++;
                    }
                    while (++i < inputlen);
                    op[++m] = xtag; // append x as a tag
                } else { //- non-ascii
                    var c0 = 0;
                    var c1 = 0;
                    var c2 = 0;
                    var c3 = 0;
                    var remaini = 0;
                    do {
                        remaini = inputlen - i;
                        if (remaini > 2) {
                            c0 = inputArr[i] >> 2;
                            c1 = (((inputArr[i] << 6) & 0xff) >> 2) | (inputArr[i + 1] >> 4);
                            c2 = (((inputArr[i + 1] << 4) & 0xff) >> 2) | (inputArr[i + 2] >> 6);
                            c3 = ((inputArr[i + 2] << 2) & 0xff) >> 2;
                            if (c0 > bpos) {
                                op[m] = xtag;
                                op[++m] = b62x[c0];
                            } else {
                                op[m] = b62x[c0];
                            }
                            if (c1 > bpos) {
                                op[++m] = xtag;
                                op[++m] = b62x[c1];
                            } else {
                                op[++m] = b62x[c1];
                            }
                            if (c2 > bpos) {
                                op[++m] = xtag;
                                op[++m] = b62x[c2];
                            } else {
                                op[++m] = b62x[c2];
                            }
                            if (c3 > bpos) {
                                op[++m] = xtag;
                                op[++m] = b62x[c3];
                            } else {
                                op[++m] = b62x[c3];
                            }
                            i += 2;
                        } else if (remaini == 2) {
                            c0 = inputArr[i] >> 2;
                            c1 = (((inputArr[i] << 6) & 0xff) >> 2) | (inputArr[i + 1] >> 4);
                            c2 = ((inputArr[i + 1] << 4) & 0xff) >> 4;
                            if (c0 > bpos) {
                                op[m] = xtag;
                                op[++m] = b62x[c0];
                            } else {
                                op[m] = b62x[c0];
                            }
                            if (c1 > bpos) {
                                op[++m] = xtag;
                                op[++m] = b62x[c1];
                            } else {
                                op[++m] = b62x[c1];
                            }
                            if (c2 > bpos) {
                                op[++m] = xtag;
                                op[++m] = b62x[c2];
                            } else {
                                op[++m] = b62x[c2];
                            }
                            i += 1;
                        } else { // ==1
                            c0 = inputArr[i] >> 2;
                            c1 = ((inputArr[i] << 6) & 0xff) >> 6;
                            if (c0 > bpos) {
                                op[m] = xtag;
                                op[++m] = b62x[c0];
                            } else {
                                op[m] = b62x[c0];
                            }
                            if (c1 > bpos) {
                                op[++m] = xtag;
                                op[++m] = b62x[c1];
                            } else {
                                op[++m] = b62x[c1];
                            }
                        }
                        m++;
                    }
                    while (++i < inputlen);
                }
                rtn = op.join('');
            }
            return rtn;
        }

        //- decode, statically
        this.decode = function(input, obase) {
            var rtn = undefined;
            if (typeof input == 'undefined' || input == '') {
                return rtn;
            }
            var codetype = 1;
            var xtag = this.get('xtag');
            var b62x = this.get('b62x');
            var asclist = this.get('asclist');
            var ascrlist = this.get('ascrlist');
            var bpos = this.get('bpos');
            var xpos = this.get('xpos');
            var ascidx = this.get('ascidx');
            var ascmax = this.get('ascmax');
            var rb62x = fillRb62x(b62x, bpos, xpos);
            var isnum = false;
            if (obase > 0) {
                isnum = true;
            }
            if (isnum) {
                rtn = 0;
                var ibase = xpos;
                var num_input = xx2dec(input, ibase, rb62x);
                rtn = dec2xx(num_input, obase, b62x);
                // why a medille num_input is needed? for double check?
            } else {
                // string
                var inputArr = toUTF8Array(input); // this.str2ab(input); //input.split(''); // need '' as parameter
                var inputlen = inputArr.length;
                var setResult = this.setAscii(codetype, inputArr, ascidx, ascmax, asclist, ascrlist);
                var asctype = setResult['asctype'];
                ascidx = setResult['ascidx'];
                ascrlist = setResult['ascrlist'];
                var op = [];
                var i = 0;
                var m = 0;
                var ixtag = xtag.charCodeAt();
                if (asctype == 1) { // ascii
                    inputlen--; // pop the last one as 'x'
                    var tmpc = '';
                    do {
                        if (inputArr[i] == ixtag) {
                            if (inputArr[i + 1] == ixtag) {
                                op[m] = xtag;
                                i++;
                            } else {
                                tmpc = String.fromCharCode(inputArr[++i]);
                                op[m] = String.fromCharCode(ascrlist[tmpc]);
                            }
                        } else {
                            op[m] = String.fromCharCode(inputArr[i]);
                        }
                        m++;
                    }
                    while (++i < inputlen);
                    rtn = op.join('');
                } else { // non-ascii
                    var tmpArr = [];
                    var tmprtn = {};
                    var bint = {
                        1: 1,
                        2: 2,
                        3: 3
                    };
                    var remaini = 0;
                    var rki = 0;
                    var j = 0;
                    for (var rk in rb62x) { // for char and its ascii value as key
                        rki = rk.charCodeAt();
                        rb62x[rki] = rb62x[rk];
                    }
                    for (var rk in bint) { // for char and its ascii value as key
                        rki = rk.charCodeAt();
                        bint[rki] = bint[rk];
                    }
                    do {
                        tmpArr = [];
                        remaini = inputlen - i;
                        if (remaini > 1) {
                            j = 0;
                            do {
                                if (inputArr[i] == ixtag) {
                                    i++;
                                    tmpArr[j] = bpos + bint[inputArr[i]];
                                } else {
                                    tmpArr[j] = rb62x[inputArr[i]];
                                }
                                i++;
                                j++;
                            }
                            while (j < 4 && i < inputlen);

                            tmprtn = decodeByLength(tmpArr, op, m);
                            op = tmprtn[0];
                            m = tmprtn[1]; //- deprecated.
                        } else {
                            throw 'Base62x.decode: illegal base62x input:[' + input + '].';
                        }
                        m++;
                    }
                    while (i < inputlen);
                    rtn = toUTF16Array(op).join(''); //String.fromCharCode.apply(null, new Uint8Array(op));
                }
            }
            return rtn;
        }

        //- methods, private
        //-
        this.get = function(k) {
            var ret = undefined;
            //- constant config
            this.config = {
                'xtag': 'x',
                'b62x': ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
                    'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b',
                    'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
                    'q', 'r', 's', 't', 'u', 'v', 'w', 'y', 'z', '1', '2', '3', 'x'
                ],
                'bpos': 60,
                'xpos': 64,
                'rb62x': [],
                'ascmax': 127,
                'asclist': ['4', '5', '6', '7', '8', '9', '0',
                    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
                    'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b',
                    'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
                    'q', 'r', 's', 't', 'u', 'v', 'w', 'y', 'z'
                ],
                'ascidx': [],
                'ascrlist': [],
                'max_safe_base': 36,
                'base59': 59
            };
            var gotV = false;
            //- runtime
            if (typeof this.configx != 'undefined') {
                if (this.configx.hasOwnProperty(k)) {
                    ret = this.configx[k];
                    gotV = true;
                }
            }
            //- constant
            if (!gotV) {
                if (this.config.hasOwnProperty(k)) {
                    ret = this.config[k];
                    gotV = true;
                }
            }
            return ret;
        }

        //-
        this.set = function(k, v) {
            var rtn = undefined;
            if (typeof this.configx == 'undefined') {
                this.configx = {};
            }
            if (true) {
                if (typeof v == 'string') {
                    this.configx[k] = v;
                } else {
                    this.configx[k] = v;
                }
            }
            return rtn;
        }

        //-
        fillRb62x = function(b62x, bpos, xpos) {
            var rb62x = {};
            for (var i = 0; i <= xpos; i++) {
                if (i > bpos && i < xpos) {
                    //omit x1, x2, x3
                } else {
                    rb62x[b62x[i]] = i;
                }
            }
            return rb62x;
        }

        //-
        this.setAscii = function(codetype, inputArr, ascidx, ascmax, asclist, ascrlist) {
            var rtn = {};
            var asctype = 0;
            var xtag = this.get('xtag');
            var ixtag = xtag.charCodeAt();
            var inputlen = inputArr.length;
            if (codetype == 0 && inputArr[0] <= ascmax) {
                asctype = 1;
                var tmpi = 0;
                for (var i = 1; i < inputlen; i++) {
                    tmpi = inputArr[i];
                    if (tmpi > ascmax ||
                        (tmpi > 16 && tmpi < 21) //DC1-4
                        ||
                        (tmpi > 27 && tmpi < 32)) { //FC, GS, RS, US
                        asctype = 0;
                        break;
                    }
                }
            } else if (codetype == 1 && inputArr[inputlen - 1] == ixtag) {
                asctype = 1;
            }
            rtn['asctype'] = asctype;
            if (asctype == 1) {
                for (var i = 0; i < ascmax; i++) {
                    ascidx[i] = -1;
                }
                var idxi = 0;
                var bgnArr = [0, 21, 32, 58, 91, 123];
                var endArr = [17, 28, 48, 65, 97, ascmax + 1];
                for (var k in bgnArr) {
                    var v1 = bgnArr[k];
                    var v2 = endArr[k];
                    for (var i = v1; i < v2; i++) {
                        ascidx[i] = asclist[idxi];
                        ascrlist[asclist[idxi]] = i;
                        idxi++;
                    }
                }
            }
            rtn['ascidx'] = ascidx;
            rtn['ascrlist'] = ascrlist;
            return rtn;
        }

        //-
        xx2dec = function(input, ibase, rb62x) {
            var rtn = 0;
            var obase = 10;
            var xtag = this.get('xtag');
            var bpos = this.get('bpos');
            var max_safe_base = this.get('max_safe_base');
            var xpos = this.get('xpos');
            var base59 = this.get('base59');
            if (ibase < 2 || ibase > xpos) {
                return rtn;
            } else if (ibase <= max_safe_base) {
                rtn = parseInt(input + '', ibase | 0).toString(obase | 0); //http://locutus.io/php/math/base_convert/
            } else {
                var isBase62x = false;
                if (ibase > base59 && ibase < xpos) {
                    rb62x['x'] = 59;
                    rb62x['y'] = 60;
                    rb62x['z'] = 61;
                } else if (ibase == xpos) {
                    isBase62x = true;
                }
                var iArr = input.split('');
                var aLen = iArr.length;
                var xnum = 0;
                var tmpi = 0;
                iArr.reverse();
                for (var i = 0; i < aLen; i++) {
                    if (isBase62x && iArr[i + 1] == xtag) {
                        tmpi = bpos + rb62x[iArr[i]];
                        xnum++;
                        i++;
                    } else {
                        tmpi = rb62x[iArr[i]];
                    }
                    rtn += tmpi * Math.pow(ibase, (i - xnum));
                }
                //- oversize check
                //- @todo
            }
            return rtn;
        }

        //-
        dec2xx = function(num_input, obase, b62x) {
            var rtn = 0;
            var ibase = 10;
            var xtag = this.get('xtag');
            var bpos = this.get('bpos');
            var max_safe_base = this.get('max_safe_base');
            var xpos = this.get('xpos');
            var num_input_orig = num_input;
            var base59 = this.get('base59');
            if (obase < 2 || obase > xpos) {
                return rtn;
            } else if (obase <= max_safe_base) {
                rtn = parseInt(num_input + '', ibase | 0).toString(obase | 0);
            } else {
                var isBase62x = false;
                if (obase > base59 && obase < xpos) {
                    b62x[59] = 'x';
                    b62x[60] = 'y';
                    b62x[61] = 'z';
                } else if (obase == xpos) {
                    isBase62x = true;
                }
                var maxPos = bpos;
                if (!isBase62x) {
                    maxPos = bpos + 1;
                }
                var i = 0;
                var b = 0;
                var oArr = [];
                while (num_input >= obase) {
                    b = num_input % obase;
                    num_input = Math.floor(num_input / obase);
                    if (b <= maxPos) {
                        oArr[i++] = b62x[b];
                    } else {
                        oArr[i++] = b62x[b - bpos];
                        oArr[i++] = xtag;
                    }
                }
                b = num_input;
                if (b <= maxPos) {
                    oArr[i++] = b62x[b];
                } else {
                    oArr[i++] = b62x[b - bpos];
                    oArr[i++] = xtag;
                }
                oArr.reverse();
                rtn = oArr.join('');
            }
            return rtn;
        }


        //-
        decodeByLength = function(tmpArr, op, m) {
            var rtn = {};
            var c0 = 0;
            var c1 = 0;
            var c2 = 0;
            if (typeof tmpArr[3] != 'undefined') {
                c0 = tmpArr[0] << 2 | tmpArr[1] >> 4;
                c1 = ((tmpArr[1] << 4) & 0xf0) | (tmpArr[2] >> 2);
                c2 = ((tmpArr[2] << 6) & 0xff) | tmpArr[3];
                op[m] = c0;
                op[++m] = c1;
                op[++m] = c2;
            } else if (typeof tmpArr[2] != 'undefined') {
                c0 = tmpArr[0] << 2 | tmpArr[1] >> 4;
                c1 = ((tmpArr[1] << 4) & 0xf0) | tmpArr[2];
                op[m] = c0;
                op[++m] = c1;
            } else if (typeof tmpArr[1] != 'undefined') {
                c0 = tmpArr[0] << 2 | tmpArr[1];
                op[m] = c0;
            } else {
                c0 = tmpArr[0];
                op[m] = c0; //String.fromCharCode(c0);
            }
            rtn = {
                0: op,
                1: m
            };
            return rtn;
        }

        //-
        toUTF8Array = function(utf16Str) { // http://stackoverflow.com/questions/18729405/how-to-convert-utf8-string-to-byte-array
            var utf8 = [];
            var str = utf16Str;
            for (var i = 0; i < str.length; i++) {
                var charcode = str.charCodeAt(i);
                if (charcode < 0x80) {
                    utf8.push(charcode);
                } // one byte
                else if (charcode < 0x800) { // two bytes
                    utf8.push(0xc0 | (charcode >> 6),
                        0x80 | (charcode & 0x3f));
                } else if (charcode < 0xd800 || charcode >= 0xe000) { // three bytes
                    utf8.push(0xe0 | (charcode >> 12),
                        0x80 | ((charcode >> 6) & 0x3f),
                        0x80 | (charcode & 0x3f));
                } else { // surrogate pair, four bytes
                    i++;
                    // UTF-16 encodes 0x10000-0x10FFFF by
                    // subtracting 0x10000 and splitting the
                    // 20 bits of 0x0-0xFFFFF into two halves
                    charcode = 0x10000 + (((charcode & 0x3ff) << 10) |
                        (str.charCodeAt(i) & 0x3ff));
                    utf8.push(0xf0 | (charcode >> 18),
                        0x80 | ((charcode >> 12) & 0x3f),
                        0x80 | ((charcode >> 6) & 0x3f),
                        0x80 | (charcode & 0x3f));
                }
            }
            return utf8;
        }

        //-
        toUTF16Array = function(utf8Bytes) { //https://terenceyim.wordpress.com/2011/03/04/javascript-utf-8-codec-that-supports-supplementary-code-points/
            var bytes = utf8Bytes;
            var len = bytes.length;
            var result = [];
            var code, i, j;
            j = 0;
            for (i = 0; i < len; i++) {
                if (bytes[i] <= 0x7f) { // one byte
                    result[j++] = String.fromCharCode(bytes[i]);
                } else if (bytes[i] >= 0xc0) { // Mutlibytes
                    if (bytes[i] < 0xe0) { // two bytes
                        code = ((bytes[i++] & 0x1f) << 6) |
                            (bytes[i] & 0x3f);
                    } else if (bytes[i] < 0xf0) { // three bytes
                        code = ((bytes[i++] & 0x0f) << 12) |
                            ((bytes[i++] & 0x3f) << 6) |
                            (bytes[i] & 0x3f);
                    } else { // four bytes
                        // turned into two characters in JS as surrogate pair
                        code = (((bytes[i++] & 0x07) << 18) |
                            ((bytes[i++] & 0x3f) << 12) |
                            ((bytes[i++] & 0x3f) << 6) |
                            (bytes[i] & 0x3f)) - 0x10000;
                        // High surrogate
                        result[j++] = String.fromCharCode(((code & 0xffc00) >>> 10) + 0xd800);
                        // Low surrogate
                        code = (code & 0x3ff) + 0xdc00;
                    }
                    result[j++] = String.fromCharCode(code);
                }
            }
            return result;
        }
    }
    var base62 = new YYTBase62();
    return {
        encode: base62.encode,
        decode: base62.decode,
        get: base62.get,
        set: base62.set,
        setAscii: base62.setAscii
    }
}));
/**
 * 类继承工具
 */
(function(root, factory) {

    'use strict';

    if (typeof define === 'function' && define.amd) {
        define(factory);
    } else if (typeof exports !== 'undefined') {
        module.exports = factory();
    } else {
        root.yytExtend = factory();
    }

}(this, function() {

    var io = function(o) {
        for (var m in o) {
            this[m] = o[m];
        }
    };
    var oc = Object.prototype.constructor;

    // 重写原型
    function override(origclass, overrides) {
        if (overrides) {
            var p = origclass.prototype;
            $.extend(p, overrides);
            if (yytUtil.isIE && overrides.hasOwnProperty('toString')) {
                p.toString = overrides.toString;
            }
        }
    }

    // 继承
    function extend(sb, sp, overrides) {
        if (typeof sp == 'object') {
            overrides = sp;
            sp = sb;
            sb = overrides.constructor != oc ? overrides.constructor : function() {
                sp.apply(this, arguments);
            };
        }
        var F = function() {},
            sbp,
            spp = sp.prototype;

        F.prototype = spp;
        sbp = sb.prototype = new F();
        sbp.constructor = sb;
        sb.superclass = spp;
        if (spp.constructor == oc) {
            spp.constructor = sp;
        }
        sb.override = function(o) {
            override(sb, o);
        };
        sbp.superclass = sbp.supr = (function() {
            return spp;
        });
        sbp.override = io;
        override(sb, overrides);
        sb.extend = function(o) {
            return $.extend(sb, o);
        };
        return sb;
    }

    return extend;
}));
/**
 * 模态框工具
 */
(function(root, factory) {

    'use strict';

    if (typeof define === 'function' && define.amd) {
        define(factory);
    } else if (typeof exports !== 'undefined') {
        module.exports = factory();
    } else {
        root.yytModal = factory();
    }

}(this, function() {

    function isIELowLv() {
        var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串
        var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1; //判断是否IE<11浏览器
        // var isEdge = userAgent.indexOf("Edge") > -1 && !isIE; //判断是否IE的Edge浏览器
        // var isIE11 = userAgent.indexOf('Trident') > -1 && userAgent.indexOf("rv:11.0") > -1;
        if (isIE) {
            var reIE = new RegExp("MSIE (\\d+\\.\\d+);");
            reIE.test(userAgent);
            var fIEVersion = parseFloat(RegExp["$1"]);
            if (fIEVersion == 8 || fIEVersion == 9) {
                return true;
            } else {
                return false
            }
        }
        return false
    }

    var count = 0;

    /**
     * 显示modal
     * @param config
     */
    function yytModal(config) {
        var elId = Date.parse(new Date()) + count;
        config = config ? config : {};
        var html = config.content || "";
        var footer = '';
        if (config.isShowFooter) {
            if (config.btns) {
                footer += '<div class="yyt-modal-footer" id="foot-' + elId + '">';
                for (var btn in config.btns) {
                    footer += '<div class="footer-btn-wrap">';
                    footer += '<button class="yyt-btn yyt-btn-' + config.btns[btn].type + ' ' + (config.btns[btn].clazz || '') + '" id="' + btn + '" style="margin-right: 10px">' + config.btns[btn].text + '</button>';
                    footer += '</div>';
                }
            } else {
                footer += '<div class="yyt-modal-footer" id="foot-' + elId + '">' +
                    '<div class="footer-btn-wrap">' +
                    '<button class="yyt-btn cancel" data-dismiss="modal">取消</button> ' +
                    '<button class="yyt-btn yyt-btn-primary confirm" style="margin-right: 10px">确定</button>' +
                    '</div>';
            }
            if (config.tip) {
                footer += '<div class="footer-tips">' +
                    '<p></p>' +
                    '</div>';
            }
            footer += '</div>';
        }
        var enableClose = config.enableClose;
        if (typeof config.enableClose == 'undefined') {
            enableClose = true
        }
        if (!config.height) {
            config.maxHeight = null;
        }
        var modal = $.yyt_modal({
            title: config.title || '', //title
            type: config.type, // weizf+ 20210425 type判断是否是模态框类型 type:iframe为iframe类型的modal
            onload: config.onload, // weizf+ 20210425 仅当为模态框类型时有效，当为模态框类型时模态框内页面加载完触发onload事件
            content: html, //内容
            footer: footer, //footer内容
            target: '#yyt-modal-' + elId,
            cssclass: (config.cssclass || config.className || '') + ' ' + (isIELowLv() ? 'is-low-IE' : ''), //自定义类名
            isShowClose: config.isShowClose || false, //是否显示close，废弃
            enableClose: enableClose, //是否显示close，废弃
            maxmin: config.maximizable || false, //是否支持全屏
            isDefaultMax: config.isMax || false, //是否默认全屏
            maskClosable: config.maskClosable || false, //遮罩是否可关闭
            nobackdrop: config.isNoMask || false, //遮罩是否可关闭
            width: config.width || null, //宽度
            height: config.height || null, //高度
            maxHeight: config.maxHeight || null, //最大高度
            zIndex: config.zIndex,
            resize: false, // 允许拖拽改变大小
            beforeClose: config.beforeClose, //关闭前事件
            closeIsDestory: typeof config.closeIsDestory === 'boolean' ? config.closeIsDestory : true //关闭是否销毁模态框
        });
        modal.render();

        count++;

        $('body').on('click', "#yyt-modal-" + elId + " .yyt-btn", function() {
            if (!config.btns || !config.btns[$(this).attr('id')]) return;
            if (typeof config.btns[$(this).attr('id')].handler === 'function')
                config.btns[$(this).attr('id')].handler.call(this, modal);
        });
        $('body').on('click', "#yyt-modal-" + elId + " .close", function(e) {
            e.stopPropagation();
            if (typeof config.cancel == 'function') {
                var result = config.cancel.call(this, modal);
                if (result !== false) {
                    modal.destroy();
                }
            } else {
                modal.destroy();
            }
        });
        $('body').on('click', "#foot-" + elId + " .confirm", function() {
            if (typeof config.confirm == 'function') {
                config.confirm.call(this, modal)
            }
        });
        $('body').on('click', "#foot-" + elId + " .cancel", function() {
            if (typeof config.cancel == 'function') {
                var result = config.cancel.call(this, modal);
                if (result !== false) {
                    modal.destroy();
                }
            } else {
                modal.destroy();
            }
        });
        if ((config.isNoDrag !== false || config.isDrag === true) && config.maximizable !== true) {
            addDragEvent(elId);
        }
        if (config.maskClosable) {
            modal.$modal.on('click', function(e) {
                if ($(e.target).hasClass('yyt-modal-wrap')) {
                    modal.destroy();
                }
            });
        }
        //如果有iframe
        var $iframe = modal.$modal.find('iframe');
        var $headerWrap = $('#yyt-modal-' + elId).find('.yyt-modal-header');
        if ($iframe.length != 0) {
            var orgiHref = ''; //原始的href
            var iframe = $iframe[0];

            function afterIframeLoaded() {
                if (!orgiHref) {
                    orgiHref = $iframe[0].contentWindow.location.href;
                }
                //iframe加载完成后你需要进行的操作
                if ($iframe[0].contentWindow.location.href != orgiHref) {
                    $headerWrap.prepend('<i class="yyt-icon icon-back"></i>');
                    $headerWrap.find('.icon-back').on('click', function() {
                        $iframe[0].contentWindow.history.go(-1);
                    });
                } else {
                    if ($headerWrap.find('.icon-back').length != 0) {
                        $headerWrap.find('.icon-back').remove();
                    }
                }
            }

            // 禁用模态框返回
            if (!config.disableBack) {
                $iframe.load(function() {
                    afterIframeLoaded();
                });
            }
            // if (iframe.attachEvent) {
            //     iframe.attachEvent("onload", function() {
            //         afterIframeLoaded();
            //     });
            // } else {
            //     iframe.onload = function() {
            //         afterIframeLoaded();
            //     };
            // }
        }

        //设置模态框提示
        modal.setTip = function(tip) {
            if ($(this.options.target).find(".footer-tips").length > 0) {
                $(this.options.target).find(".footer-tips p").html(tip);
            } else {
                var tipHtml = '<div class="footer-tips">' +
                    '<p>' + tip + '</p>' +
                    '</div>';
                $(this.options.target).find(".yyt-modal-footer").append(tipHtml);
            }
        };

        if (config.tip) {
            modal.setTip(config.tip);
        }

        // add by caiwc 20200425 模态框支持拖拽改变大小
        if (config.resize && !yytUtil.isIE8) {
            var $dragger = $('<div class="resize-dragger"></div>').appendTo(modal.$main);
            $($dragger).mousedown(function() {
                var offset = modal.$main.offset();
                modal.$main.css({
                    position: "absolute",
                    top: offset.top,
                    left: offset.left
                });
            });
            yytDragResize(modal.$main[0], $dragger[0], false, false, false, false);
            yytEleResize.on(modal.$main[0], function() {
                var height = modal.$main.height() - modal.$main.children('.yyt-modal-header').outerHeight() - modal.$main.children('.yyt-modal-footer').outerHeight();
                modal.$inner.height(height);
            });
        }

        return modal;
    }

    //头部拖动事件
    function addDragEvent(elId) {
        //拖拽
        var mx = 0,
            my = 0; //鼠标x、y轴坐标（相对于left，top）
        var dx = 0,
            dy = 0; //对话框坐标（同上）
        var isDraging = false; //不可拖动
        var $yytModal = $('#yyt-modal-' + elId);
        var $header = $yytModal.find('.yyt-modal-header');
        $header.addClass('yyt-drag');
        //鼠标按下
        $header.mousedown(function(e) {
            e = e || window.event;
            mx = e.pageX; //点击时鼠标X坐标
            my = e.pageY; //点击时鼠标Y坐标
            dx = $yytModal.offset().left;
            dy = $yytModal.offset().top;
            isDraging = true; //标记对话框可拖动
        });

        //鼠标移动更新窗口位置
        $(document).mousemove(function(e) {
            var e = e || window.event;
            var x = e.pageX; //移动时鼠标X坐标
            var y = e.pageY; //移动时鼠标Y坐标
            if (isDraging) { //判断对话框能否拖动
                var moveX = dx + x - mx; //移动后对话框新的left值
                var moveY = dy + y - my; //移动后对话框新的top值
                if (moveY < 0) {
                    moveY = 0;
                }
                //重新设置对话框的left、top
                $yytModal.css({
                    position: 'absolute',
                    "left": moveX + 'px',
                    "top": moveY + 'px',
                    marginTop: 0
                });

            }
        });

        //鼠标离开
        $(document).mouseup(function() {
            isDraging = false;
        });
    }

    return yytModal
}));
/**
 * 全屏事件
 */
(function(root, factory) {

    'use strict';

    if (typeof define === 'function' && define.amd) {
        define(factory);
    } else if (typeof exports !== 'undefined') {
        module.exports = factory();
    } else {
        root.yytScaling = factory();
    }

}(this, function() {
    /**
     * 全屏事件
     */
    function fullscreen() {
        if (document.fullscreenElement ||
            document.mozFullScreenElement ||
            document.webkitFullscreenElement ||
            document.msFullscreenElement) {
            if (document.exitFullscreen) {
                document.exitFullscreen();
            } else if (document.mozCancelFullScreen) {
                document.mozCancelFullScreen();
            } else if (document.webkitExitFullscreen) {
                document.webkitExitFullscreen();
            } else if (document.msExitFullscreen) {
                document.msExitFullscreen();
            }
        } else {
            if (document.documentElement.requestFullscreen) {
                document.documentElement.requestFullscreen();
            } else if (document.documentElement.mozRequestFullScreen) {
                document.documentElement.mozRequestFullScreen();
            } else if (document.documentElement.webkitRequestFullscreen) {
                document.documentElement.webkitRequestFullscreen();
            } else if (document.documentElement.msRequestFullscreen) {
                document.documentElement.msRequestFullscreen();
            } else if (typeof window.ActiveXObject != "undefined") {
                try {
                    //for IE，这里其实就是模拟了按下键盘的F11，使浏览器全屏
                    var wscript = new ActiveXObject("WScript.Shell");
                    if (wscript != null) {
                        wscript.SendKeys("{F11}");
                    }
                } catch (error) {
                    yytUtil.msg.showWarnMsg('浏览器不支持全屏API或已被禁用,IE9请开放ActiveX控件')
                }
            }
        }
    }

    return {
        fullscreen: fullscreen
    }
}));

/**
 *
 * yytStorage - - localStorage工具
 * @author caiwc 277600202@qq.com
 * @date 2017-08-01
 *
 * 如果有支持localStorage则使用localStorage
 * 如果没有支持localStorage且支持userData 则使用userData
 *
 * 代码支持 CommonJS, AMD, global(window)环境下运行
 */

(function(root, factory) {

    'use strict';

    if (typeof define === 'function' && define.amd) {
        define(factory);
    } else if (typeof exports !== 'undefined') {
        module.exports = factory();
    } else {
        root.yytStorage = factory();
    }

}(this, function() {

    /**
     * 判断是否支持localStorage
     * @return {*}
     */
    function isLocalStorageValid() {
        try {
            return typeof localStorage !== 'undefined' &&
                ('setItem' in localStorage) &&
                localStorage.setItem;
        } catch (e) {
            return false;
        }
    }

    /**
     * 实现基于IE的userData存储
     * @constructor
     */
    function UserDataStorage() {

        var keys = {};

        var memory = document.createElement("div");
        memory.style.display = "none";
        memory.style.behavior = "url('#default#userData')"; // 附加userData行为
        document.body.appendChild(memory);

        memory.load("UserDataStorage");

        // 提示userdata并不支持事件
        var consoleWarn = function(funname) {
            if (console && console.warn) console.warn("this browser storage is not support " + funname + " function.");
        };

        this.setItem = function(key, value) {
            memory.setAttribute(key, value); // 以设置属性的形式保存数据
            memory.save("UserDataStorage"); // 保存数据改变后的状态
            keys[key] = 1; //  保存key, 在clear的时候能用上
        };

        this.getItem = function(key) {
            return memory.getAttribute(key) || null;
        };

        this.removeItem = function(key) {
            memory.removeAttribute(key);
            memory.save("UserDataStorage");
            keys[key] = null;
        };

        this.clear = function() {
            consoleWarn("clear");

            for (var key in keys) {
                if (keys[key]) {
                    memory.removeAttribute(key);
                }
            }
            memory.save("UserDataStorage");
        }
    }

    Array.prototype.removeByValue = function(val) {
        for (var i = 0; i < this.length; i++) {
            if (this[i] == val) {
                this.splice(i, 1);
                break;
            }
        }
    };

    // storage api ========================================

    // storage
    var Storage = null;

    function getStorage() {
        if (Storage)
            return Storage;
        if (isLocalStorageValid()) {
            Storage = localStorage;
        } else {
            Storage = new UserDataStorage();
        }
        return Storage;
    }


    // 键值改变事件
    var events = {};

    /**
     * 根据键获取值
     * @param key
     */
    var getItem = function(key) {
        var item = JSON.parse(getStorage().getItem(key));
        if (!item) return null;
        if (item.isObject) {
            return JSON.parse(item.value);
        }
        return item.value;
    };

    var getSessionStorageItem = function(key) {
        var item = JSON.parse(sessionStorage.getItem(key));
        if (!item) return null;
        if (item.isObject) {
            return JSON.parse(item.value);
        }
        return item.value;
    };

    var setSessionStorageItem = function(key, value) {
        var item = {};
        if (typeof value == 'object') {
            item['isObject'] = 1;
            item['value'] = JSON.stringify(value);
        } else {
            item['value'] = value;
        }

        var oldValue = getSessionStorageItem(key);

        sessionStorage.setItem(key, JSON.stringify(item));

        fireEvents({
            key: key,
            oldValue: oldValue,
            newValue: value
        });
    };

    /**
     * 设置键值对
     * @param key
     * @param value
     */
    var setItem = function(key, value) {
        var item = {};
        if (typeof value == 'object') {
            item['isObject'] = 1;
            item['value'] = JSON.stringify(value);
        } else {
            item['value'] = value;
        }

        var oldValue = getItem(key);

        getStorage().setItem(key, JSON.stringify(item));

        fireEvents({
            key: key,
            oldValue: oldValue,
            newValue: value
        });
    };

    /**
     * 移除缓存
     * @param key
     */
    var removeItem = function(key) {
        var oldValue = getItem(key);
        getStorage().removeItem(key);
        fireEvents({
            key: key,
            oldValue: oldValue,
            newValue: null
        });
    };

    /**
     * 清空存储
     */
    var clear = function() {
        getStorage().clear();
        fireEvents({
            key: null,
            oldValue: null,
            newValue: null
        });
    };

    /**
     * 拼接storage, connect默认,
     * @param key
     * @param value
     */
    var itemAppend = function(key, value, split) {
        split = split ? split : ",";
        var oldValue = getItem(key);
        if (oldValue) {
            setItem(key, oldValue + split + value);
        } else {
            setItem(key, value);
        }
    };

    var itemSplice = function(key, value, split) {
        split = split ? split : ",";
        var oldValue = getItem(key);
        if (oldValue) {
            var arr = oldValue.split(split);

            var newList = [];
            for (var i = 0; i < arr.length; i++) {
                if (arr[i] != value) {
                    newList.push(arr[i]);
                }
            }
            setItem(key, newList.join(split));
            return value;
        }
        return null;
    };

    /**
     * 增加监听
     * @param key
     * @param callback
     */
    var addEventListener = function(key, callback) {
        if (!events[key]) events[key] = [];
        if (typeof callback == 'function')
            events[key].push(callback);
    };

    /**
     * 移除监听
     * @param key
     * @param callback
     */
    var removeEventListener = function(key, callback) {
        if (events[key])
            events[key].removeByValue(callback);
    };

    // 触发监听
    var fireEvents = function(e) {
        var key = e.key;
        var oldValue = e.oldValue;
        var newValue = e.newValue;

        if (key) {
            if (events[key]) {
                for (var i = 0; i < events[key].length; i++) {
                    events[key][i].call(this, {
                        key: key,
                        oldValue: oldValue,
                        newValue: newValue
                    });
                }
            }
        } else {
            for (var j in events) {
                for (var i = 0; i < events[j].length; i++) {
                    events[j][i].call(this, {
                        key: null,
                        oldValue: null,
                        newValue: null
                    });
                }
            }
        }

    };

    function winFireEvent(e) {
        var key = e.key;
        var oldValue = e.oldValue;
        var newValue = e.newValue;

        // 如果没有监听就不走下去了。 直接调localstorage.clear的时候，key为null
        if (key && (!events[key] || events[key].length <= 0)) {
            return;
        }

        if (oldValue) {
            oldValue = JSON.parse(oldValue);
            if (oldValue.isObject) {
                oldValue = JSON.parse(oldValue.value);
            } else {
                oldValue = oldValue.value;
            }
        }

        if (newValue) {
            newValue = JSON.parse(newValue);
            if (newValue.isObject) {
                newValue = JSON.parse(newValue.value);
            } else {
                newValue = newValue.value;
            }
        }


        fireEvents({
            key: key,
            oldValue: oldValue,
            newValue: newValue
        });
    }

    if (window.addEventListener) {
        window.addEventListener('storage', winFireEvent, false);
    } else {
        window.attachEvent("onstorage", winFireEvent);
    }


    //add by  xiezf 2020/03/23 增加浏览器缓存 browserStorage TODO 没有方法监听浏览器的关闭动作
    var setBrowserStorageItem = function(key, value) {
        setItem(key, value);
        // 监听浏览器关闭
        window.onunload = function(e) { //刷新或关闭浏览器窗口
            e = e || window.event;
            console.log("我关闭了")
        };
    };

    var getBrowserStorageItem = function(key) {
        getItem(key);
    };

    return {

        itemAppend: itemAppend,

        itemSplice: itemSplice,

        setItem: setItem,

        getItem: getItem,

        removeItem: removeItem,

        clear: clear,

        addEventListener: addEventListener,

        removeEventListener: removeEventListener,

        getSessionStorageItem: getSessionStorageItem,

        setSessionStorageItem: setSessionStorageItem
    };
}));
/**
 * 浮动提示工具，取代title的直接提示
 */
(function(root, factory) {

    'use strict';

    if (typeof define === 'function' && define.amd) {
        define(factory);
    } else if (typeof exports !== 'undefined') {
        module.exports = factory();
    } else {
        root.yytTip = factory();
    }

}(this, function() {
    /**
     * tip 提示
     * @param follow
     * @param options
     */
    function yytTip(follow, options) {
        return $(follow).yyt_tooltip(options);
    }
    return yytTip
}));


/**
 * url请求工具
 */
(function(root, factory) {

    'use strict';

    if (typeof define === 'function' && define.amd) {
        define(factory);
    } else if (typeof exports !== 'undefined') {
        module.exports = factory();
    } else {
        root.yytUrl = factory();
    }

}(this, function() {
    /**
     * 解析URL
     * @param url
     */
    function parseUrl(url) {
        //modify by xiezf 20210316 将URL的反斜杠统一转成正斜杠
        if (url) {
            url = url.replace(/\\/g, "/");
        }
        var parse_url = /^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/;
        var result = parse_url.exec(url);
        var names = ['url', 'scheme', 'slash', 'host', 'port', 'path', 'query', 'hash'];
        var URL = {};
        for (var i = 0, len = names.length; i < len; i += 1) {
            URL[names[i]] = result[i];
        }
        URL['query'] = parseQuery(URL['query']);
        return URL;
    }

    /**
     * 解析查询参数
     * @param query
     * @return {{}}
     */
    function parseQuery(query) {
        if (query) {
            return (function() {
                var newQuery = {};
                var condValue = query.split('&');
                for (var i = 0; i < condValue.length; i++) {
                    if (condValue[i] && condValue[i].indexOf("=") != -1)
                        newQuery[condValue[i].split("=")[0]] = decodeURIComponent(condValue[i].split("=")[1]);
                }
                return newQuery;
            }());
        }
        return {};
    }

    var yytUrl = {
        parseUrl: parseUrl,
        parseQuery: parseQuery,
        /**
         * 获取url上的全部参数
         */
        getUrlParams: function(url) {
            return parseUrl(url || window.location.href)['query'];
        },
        /**
         * 获取url上的指定参数
         * @param key
         * @param url
         */
        getUrlParam: function(key, url, isXss) {
            var query = parseUrl(url || window.location.href)['query'];

            if (key === 'PUB_PARAMS' || isXss === false) {
                return query[key];
            } else {
                return query[key];
                // return query[key]
                //     .replace(/javascript/ig, '')
                //     .replace(/</g, '&lt;')
                //     .replace(/>/g, '&gt;')
                //     .replace(/"/g, '&quot;')
                //     .replace(/'/g, '&#39;');
            }
        },

        /**
         * 获取应用上下文路径
         */
        getContextPath: function() {
            return this.getAppPathByUrl(true);
        },

        /**
         * 获取请求上下文路径
         * @ param {Boolean} disContainApp 不包含app路径
         */
        getAppPathByUrl: function(disContainApp) {

            //当前页面
            var curTotalPath = window.document.location.href;

            //当前页面路径
            var pathName = window.document.location.pathname;

            //当前页面路径起始位置
            var pathNamePos = curTotalPath.indexOf(pathName);

            //host
            var hostPath = curTotalPath.substring(0, pathNamePos);

            //工程名
            var paths = pathName.split('/');
            paths.length = paths.length - 1;

            if (paths.length <= 0) {
                return hostPath;
            } else {
                var appPath = paths[0];
                var objectNameList = [];
                for (var i = 0; i < paths.length; i++) {
                    objectNameList.push(paths[i]);
                    if (paths[i] == 'yytcloud') {
                        appPath += '/' + paths[i];
                        continue;
                    }
                    if (paths[i].indexOf('yyt') != -1) {
                        //不要应用名
                        if (!disContainApp) {
                            appPath = objectNameList.join('/');
                        }
                        break;
                    }
                }
                return hostPath + appPath;
            }
        }
    };

    return yytUrl;
}));
/**
 * @class yytUtil
 * @global
 **/
var yytUtil = (function() {

    var isIE = navigator.userAgent.toLowerCase().indexOf('trident') > -1 ? true : false;

    function namespace() {
        var o, d;
        $.each(arguments, function(i, v) {
            d = v.split(".");
            o = window[d[0]] = window[d[0]] || {};
            $.each(d.slice(1), function(j, v2) {
                o = o[v2] = o[v2] || {};
            });
        });
        return o;
    }

    var utils = {
        __version: '202104261044',
        /**
         * ajax请求
         * @member {Object}
         */
        ajax: yytAjax,
        // 模态框
        modal: yytModal,
        // 消息提示
        msg: yytMsg,
        message: yytMsg, //兼容旧的yyt-manager
        // 浮动提示
        tip: yytTip,
        // 本地缓存
        storage: yytStorage,
        // 浏览器类型
        // isIE: /msie/.test(navigator.userAgent.toLowerCase()),
        isIE: isIE, //modify by xiezf  isIE 判断无效 改用这个
        isIE8: (function() {
            var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串
            // var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1; //判断是否IE<11浏览器
            // var isEdge = userAgent.indexOf("Edge") > -1 && !isIE; //判断是否IE的Edge浏览器
            // var isIE11 = userAgent.indexOf('Trident') > -1 && userAgent.indexOf("rv:11.0") > -1;
            if (isIE) {
                var reIE = new RegExp("MSIE (\\d+\\.\\d+);");
                reIE.test(userAgent);
                var fIEVersion = parseFloat(RegExp["$1"]);
                if (fIEVersion == 8) {
                    return true;
                } else {
                    return false;
                }
            }
            return false;
        })(),
        isMozilla: /firefox/.test(navigator.userAgent.toLowerCase()),
        isSafari: /safari/.test(navigator.userAgent.toLowerCase()),
        // 对象合并
        assign: $.extend,
        // 类继承
        extend: yytExtend,
        url: yytUrl,
        scale: yytScaling,
        deepApply: function() {
            var arr = [true];
            Array.prototype.push.apply(arr, arguments);
            return $.extend.apply(this, arr);
        },
        isEmpty: function(v, allowBlank) {
            return v === null || v === undefined || (($.isArray(v) && !v.length)) || (!allowBlank ? v === '' : false);
        },

        /**
         * @function namespace 命名空间
         */
        namespace: namespace,
        ns: namespace,
        toString: Object.prototype.toString,

        apply: function(target, source, defaults) {
            // no "this" reference for friendly out of scope calls
            if (defaults) {
                yytUtil.apply(target, defaults);
            }
            if (target && source && typeof source == 'object') {
                for (var p in source) {
                    target[p] = source[p];
                }
            }
            return target;
        },
        isArray: $.isArray,
        yytBase62: yytBase62
    };

    return utils;
}());